1cfca06d7SDimitry Andric //===-- FormatEntity.cpp --------------------------------------------------===//
212bd4897SEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
612bd4897SEd Maste //
712bd4897SEd Maste //===----------------------------------------------------------------------===//
812bd4897SEd Maste
912bd4897SEd Maste #include "lldb/Core/FormatEntity.h"
1012bd4897SEd Maste
1112bd4897SEd Maste #include "lldb/Core/Address.h"
1294994d37SDimitry Andric #include "lldb/Core/AddressRange.h"
1312bd4897SEd Maste #include "lldb/Core/Debugger.h"
14f73363f1SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
1512bd4897SEd Maste #include "lldb/Core/Module.h"
1612bd4897SEd Maste #include "lldb/Core/ValueObject.h"
1712bd4897SEd Maste #include "lldb/Core/ValueObjectVariable.h"
1812bd4897SEd Maste #include "lldb/DataFormatters/DataVisualization.h"
1994994d37SDimitry Andric #include "lldb/DataFormatters/FormatClasses.h"
2012bd4897SEd Maste #include "lldb/DataFormatters/FormatManager.h"
2194994d37SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
22e81d9d49SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
2312bd4897SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
2412bd4897SEd Maste #include "lldb/Symbol/Block.h"
2512bd4897SEd Maste #include "lldb/Symbol/CompileUnit.h"
2694994d37SDimitry Andric #include "lldb/Symbol/CompilerType.h"
2712bd4897SEd Maste #include "lldb/Symbol/Function.h"
2812bd4897SEd Maste #include "lldb/Symbol/LineEntry.h"
2912bd4897SEd Maste #include "lldb/Symbol/Symbol.h"
3094994d37SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
3112bd4897SEd Maste #include "lldb/Symbol/VariableList.h"
3212bd4897SEd Maste #include "lldb/Target/ExecutionContext.h"
3394994d37SDimitry Andric #include "lldb/Target/ExecutionContextScope.h"
34e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
3512bd4897SEd Maste #include "lldb/Target/Process.h"
3612bd4897SEd Maste #include "lldb/Target/RegisterContext.h"
3712bd4897SEd Maste #include "lldb/Target/SectionLoadList.h"
3812bd4897SEd Maste #include "lldb/Target/StackFrame.h"
3912bd4897SEd Maste #include "lldb/Target/StopInfo.h"
4012bd4897SEd Maste #include "lldb/Target/Target.h"
4112bd4897SEd Maste #include "lldb/Target/Thread.h"
4212bd4897SEd Maste #include "lldb/Utility/AnsiTerminal.h"
4394994d37SDimitry Andric #include "lldb/Utility/ArchSpec.h"
44344a3780SDimitry Andric #include "lldb/Utility/CompletionRequest.h"
4594994d37SDimitry Andric #include "lldb/Utility/ConstString.h"
4674a628f7SDimitry Andric #include "lldb/Utility/FileSpec.h"
47145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
4894994d37SDimitry Andric #include "lldb/Utility/Log.h"
4994994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
50344a3780SDimitry Andric #include "lldb/Utility/Status.h"
5174a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
5274a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
5394994d37SDimitry Andric #include "lldb/Utility/StringList.h"
5494994d37SDimitry Andric #include "lldb/Utility/StructuredData.h"
5594994d37SDimitry Andric #include "lldb/lldb-defines.h"
5694994d37SDimitry Andric #include "lldb/lldb-forward.h"
5774a628f7SDimitry Andric #include "llvm/ADT/STLExtras.h"
5874a628f7SDimitry Andric #include "llvm/ADT/StringRef.h"
5994994d37SDimitry Andric #include "llvm/Support/Compiler.h"
60ac9a064cSDimitry Andric #include "llvm/Support/Regex.h"
617fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
6274a628f7SDimitry Andric
63344a3780SDimitry Andric #include <cctype>
64344a3780SDimitry Andric #include <cinttypes>
65344a3780SDimitry Andric #include <cstdio>
66344a3780SDimitry Andric #include <cstdlib>
67344a3780SDimitry Andric #include <cstring>
6894994d37SDimitry Andric #include <memory>
6994994d37SDimitry Andric #include <type_traits>
7094994d37SDimitry Andric #include <utility>
7174a628f7SDimitry Andric
7274a628f7SDimitry Andric namespace lldb_private {
7374a628f7SDimitry Andric class ScriptInterpreter;
7474a628f7SDimitry Andric }
7574a628f7SDimitry Andric namespace lldb_private {
7674a628f7SDimitry Andric struct RegisterInfo;
7774a628f7SDimitry Andric }
7812bd4897SEd Maste
7912bd4897SEd Maste using namespace lldb;
8012bd4897SEd Maste using namespace lldb_private;
8112bd4897SEd Maste
82344a3780SDimitry Andric using Definition = lldb_private::FormatEntity::Entry::Definition;
83344a3780SDimitry Andric using Entry = FormatEntity::Entry;
84344a3780SDimitry Andric using EntryType = FormatEntity::Entry::Type;
85344a3780SDimitry Andric
8614f1b3e8SDimitry Andric enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
8712bd4897SEd Maste
88344a3780SDimitry Andric constexpr Definition g_string_entry[] = {
89344a3780SDimitry Andric Definition("*", EntryType::ParentString)};
9012bd4897SEd Maste
91344a3780SDimitry Andric constexpr Definition g_addr_entries[] = {
92344a3780SDimitry Andric Definition("load", EntryType::AddressLoad),
93344a3780SDimitry Andric Definition("file", EntryType::AddressFile)};
94344a3780SDimitry Andric
95344a3780SDimitry Andric constexpr Definition g_file_child_entries[] = {
96344a3780SDimitry Andric Definition("basename", EntryType::ParentNumber, FileKind::Basename),
97344a3780SDimitry Andric Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
98344a3780SDimitry Andric Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
99344a3780SDimitry Andric
100344a3780SDimitry Andric constexpr Definition g_frame_child_entries[] = {
101344a3780SDimitry Andric Definition("index", EntryType::FrameIndex),
102344a3780SDimitry Andric Definition("pc", EntryType::FrameRegisterPC),
103344a3780SDimitry Andric Definition("fp", EntryType::FrameRegisterFP),
104344a3780SDimitry Andric Definition("sp", EntryType::FrameRegisterSP),
105344a3780SDimitry Andric Definition("flags", EntryType::FrameRegisterFlags),
106344a3780SDimitry Andric Definition("no-debug", EntryType::FrameNoDebug),
107344a3780SDimitry Andric Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
108344a3780SDimitry Andric g_string_entry),
109344a3780SDimitry Andric Definition("is-artificial", EntryType::FrameIsArtificial),
11012bd4897SEd Maste };
11112bd4897SEd Maste
112344a3780SDimitry Andric constexpr Definition g_function_child_entries[] = {
113344a3780SDimitry Andric Definition("id", EntryType::FunctionID),
114344a3780SDimitry Andric Definition("name", EntryType::FunctionName),
115344a3780SDimitry Andric Definition("name-without-args", EntryType::FunctionNameNoArgs),
116344a3780SDimitry Andric Definition("name-with-args", EntryType::FunctionNameWithArgs),
117344a3780SDimitry Andric Definition("mangled-name", EntryType::FunctionMangledName),
118344a3780SDimitry Andric Definition("addr-offset", EntryType::FunctionAddrOffset),
119344a3780SDimitry Andric Definition("concrete-only-addr-offset-no-padding",
120344a3780SDimitry Andric EntryType::FunctionAddrOffsetConcrete),
121344a3780SDimitry Andric Definition("line-offset", EntryType::FunctionLineOffset),
122344a3780SDimitry Andric Definition("pc-offset", EntryType::FunctionPCOffset),
123344a3780SDimitry Andric Definition("initial-function", EntryType::FunctionInitial),
124344a3780SDimitry Andric Definition("changed", EntryType::FunctionChanged),
125344a3780SDimitry Andric Definition("is-optimized", EntryType::FunctionIsOptimized)};
12612bd4897SEd Maste
127344a3780SDimitry Andric constexpr Definition g_line_child_entries[] = {
128344a3780SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
129344a3780SDimitry Andric g_file_child_entries),
130344a3780SDimitry Andric Definition("number", EntryType::LineEntryLineNumber),
131344a3780SDimitry Andric Definition("column", EntryType::LineEntryColumn),
132344a3780SDimitry Andric Definition("start-addr", EntryType::LineEntryStartAddress),
133344a3780SDimitry Andric Definition("end-addr", EntryType::LineEntryEndAddress),
13412bd4897SEd Maste };
13512bd4897SEd Maste
136344a3780SDimitry Andric constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
137344a3780SDimitry Andric "file", EntryType::ModuleFile, g_file_child_entries)};
13812bd4897SEd Maste
139344a3780SDimitry Andric constexpr Definition g_process_child_entries[] = {
140344a3780SDimitry Andric Definition("id", EntryType::ProcessID),
141344a3780SDimitry Andric Definition("name", EntryType::ProcessFile, FileKind::Basename),
142344a3780SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
143344a3780SDimitry Andric g_file_child_entries)};
14412bd4897SEd Maste
145344a3780SDimitry Andric constexpr Definition g_svar_child_entries[] = {
146344a3780SDimitry Andric Definition("*", EntryType::ParentString)};
14712bd4897SEd Maste
148344a3780SDimitry Andric constexpr Definition g_var_child_entries[] = {
149344a3780SDimitry Andric Definition("*", EntryType::ParentString)};
15012bd4897SEd Maste
151344a3780SDimitry Andric constexpr Definition g_thread_child_entries[] = {
152344a3780SDimitry Andric Definition("id", EntryType::ThreadID),
153344a3780SDimitry Andric Definition("protocol_id", EntryType::ThreadProtocolID),
154344a3780SDimitry Andric Definition("index", EntryType::ThreadIndexID),
155344a3780SDimitry Andric Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
156344a3780SDimitry Andric g_string_entry),
157344a3780SDimitry Andric Definition("queue", EntryType::ThreadQueue),
158344a3780SDimitry Andric Definition("name", EntryType::ThreadName),
159344a3780SDimitry Andric Definition("stop-reason", EntryType::ThreadStopReason),
160344a3780SDimitry Andric Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
161344a3780SDimitry Andric Definition("return-value", EntryType::ThreadReturnValue),
162344a3780SDimitry Andric Definition("completed-expression", EntryType::ThreadCompletedExpression)};
16312bd4897SEd Maste
164344a3780SDimitry Andric constexpr Definition g_target_child_entries[] = {
165344a3780SDimitry Andric Definition("arch", EntryType::TargetArch)};
16612bd4897SEd Maste
16712bd4897SEd Maste #define _TO_STR2(_val) #_val
16812bd4897SEd Maste #define _TO_STR(_val) _TO_STR2(_val)
16912bd4897SEd Maste
170344a3780SDimitry Andric constexpr Definition g_ansi_fg_entries[] = {
171344a3780SDimitry Andric Definition("black",
17214f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
173344a3780SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
174344a3780SDimitry Andric Definition("green",
17514f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
176344a3780SDimitry Andric Definition("yellow",
17714f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
178344a3780SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
179344a3780SDimitry Andric Definition("purple",
18014f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
181344a3780SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
182344a3780SDimitry Andric Definition("white",
18314f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
18412bd4897SEd Maste };
18512bd4897SEd Maste
186344a3780SDimitry Andric constexpr Definition g_ansi_bg_entries[] = {
187344a3780SDimitry Andric Definition("black",
18814f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
189344a3780SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
190344a3780SDimitry Andric Definition("green",
19114f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
192344a3780SDimitry Andric Definition("yellow",
19314f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
194344a3780SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
195344a3780SDimitry Andric Definition("purple",
19614f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
197344a3780SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
198344a3780SDimitry Andric Definition("white",
19914f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
20012bd4897SEd Maste };
20112bd4897SEd Maste
202344a3780SDimitry Andric constexpr Definition g_ansi_entries[] = {
203344a3780SDimitry Andric Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
204344a3780SDimitry Andric Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
205344a3780SDimitry Andric Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
206344a3780SDimitry Andric Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
207344a3780SDimitry Andric Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
208344a3780SDimitry Andric Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
209344a3780SDimitry Andric Definition("underline",
21014f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
211344a3780SDimitry Andric Definition("slow-blink",
21214f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
213344a3780SDimitry Andric Definition("fast-blink",
21414f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
215344a3780SDimitry Andric Definition("negative",
21614f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
217344a3780SDimitry Andric Definition("conceal",
21814f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
219344a3780SDimitry Andric Definition("crossed-out",
22014f1b3e8SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
22112bd4897SEd Maste };
22212bd4897SEd Maste
223344a3780SDimitry Andric constexpr Definition g_script_child_entries[] = {
224344a3780SDimitry Andric Definition("frame", EntryType::ScriptFrame),
225344a3780SDimitry Andric Definition("process", EntryType::ScriptProcess),
226344a3780SDimitry Andric Definition("target", EntryType::ScriptTarget),
227344a3780SDimitry Andric Definition("thread", EntryType::ScriptThread),
228344a3780SDimitry Andric Definition("var", EntryType::ScriptVariable),
229344a3780SDimitry Andric Definition("svar", EntryType::ScriptVariableSynthetic),
230344a3780SDimitry Andric Definition("thread", EntryType::ScriptThread)};
23112bd4897SEd Maste
232344a3780SDimitry Andric constexpr Definition g_top_level_entries[] = {
233344a3780SDimitry Andric Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
234344a3780SDimitry Andric g_addr_entries),
235344a3780SDimitry Andric Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
236344a3780SDimitry Andric Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
237344a3780SDimitry Andric Definition("current-pc-arrow", EntryType::CurrentPCArrow),
238344a3780SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::File,
239344a3780SDimitry Andric g_file_child_entries),
240344a3780SDimitry Andric Definition("language", EntryType::Lang),
241344a3780SDimitry Andric Entry::DefinitionWithChildren("frame", EntryType::Invalid,
242344a3780SDimitry Andric g_frame_child_entries),
243344a3780SDimitry Andric Entry::DefinitionWithChildren("function", EntryType::Invalid,
244344a3780SDimitry Andric g_function_child_entries),
245344a3780SDimitry Andric Entry::DefinitionWithChildren("line", EntryType::Invalid,
246344a3780SDimitry Andric g_line_child_entries),
247344a3780SDimitry Andric Entry::DefinitionWithChildren("module", EntryType::Invalid,
248344a3780SDimitry Andric g_module_child_entries),
249344a3780SDimitry Andric Entry::DefinitionWithChildren("process", EntryType::Invalid,
250344a3780SDimitry Andric g_process_child_entries),
251344a3780SDimitry Andric Entry::DefinitionWithChildren("script", EntryType::Invalid,
252344a3780SDimitry Andric g_script_child_entries),
253344a3780SDimitry Andric Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
254344a3780SDimitry Andric g_svar_child_entries, true),
255344a3780SDimitry Andric Entry::DefinitionWithChildren("thread", EntryType::Invalid,
256344a3780SDimitry Andric g_thread_child_entries),
257344a3780SDimitry Andric Entry::DefinitionWithChildren("target", EntryType::Invalid,
258344a3780SDimitry Andric g_target_child_entries),
259344a3780SDimitry Andric Entry::DefinitionWithChildren("var", EntryType::Variable,
260344a3780SDimitry Andric g_var_child_entries, true)};
26112bd4897SEd Maste
262344a3780SDimitry Andric constexpr Definition g_root = Entry::DefinitionWithChildren(
263344a3780SDimitry Andric "<root>", EntryType::Root, g_top_level_entries);
26412bd4897SEd Maste
Entry(llvm::StringRef s)26514f1b3e8SDimitry Andric FormatEntity::Entry::Entry(llvm::StringRef s)
26614f1b3e8SDimitry Andric : string(s.data(), s.size()), printf_format(), children(),
267145449b1SDimitry Andric type(Type::String) {}
26812bd4897SEd Maste
Entry(char ch)26914f1b3e8SDimitry Andric FormatEntity::Entry::Entry(char ch)
270145449b1SDimitry Andric : string(1, ch), printf_format(), children(), type(Type::String) {}
27112bd4897SEd Maste
AppendChar(char ch)27214f1b3e8SDimitry Andric void FormatEntity::Entry::AppendChar(char ch) {
27312bd4897SEd Maste if (children.empty() || children.back().type != Entry::Type::String)
27412bd4897SEd Maste children.push_back(Entry(ch));
27512bd4897SEd Maste else
27612bd4897SEd Maste children.back().string.append(1, ch);
27712bd4897SEd Maste }
27812bd4897SEd Maste
AppendText(const llvm::StringRef & s)27914f1b3e8SDimitry Andric void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
28012bd4897SEd Maste if (children.empty() || children.back().type != Entry::Type::String)
28112bd4897SEd Maste children.push_back(Entry(s));
28212bd4897SEd Maste else
28312bd4897SEd Maste children.back().string.append(s.data(), s.size());
28412bd4897SEd Maste }
28512bd4897SEd Maste
AppendText(const char * cstr)28614f1b3e8SDimitry Andric void FormatEntity::Entry::AppendText(const char *cstr) {
28712bd4897SEd Maste return AppendText(llvm::StringRef(cstr));
28812bd4897SEd Maste }
28912bd4897SEd Maste
29014f1b3e8SDimitry Andric #define ENUM_TO_CSTR(eee) \
29114f1b3e8SDimitry Andric case FormatEntity::Entry::Type::eee: \
29214f1b3e8SDimitry Andric return #eee
29312bd4897SEd Maste
TypeToCString(Type t)29414f1b3e8SDimitry Andric const char *FormatEntity::Entry::TypeToCString(Type t) {
29514f1b3e8SDimitry Andric switch (t) {
29612bd4897SEd Maste ENUM_TO_CSTR(Invalid);
29712bd4897SEd Maste ENUM_TO_CSTR(ParentNumber);
29812bd4897SEd Maste ENUM_TO_CSTR(ParentString);
2995f29bb8aSDimitry Andric ENUM_TO_CSTR(EscapeCode);
30012bd4897SEd Maste ENUM_TO_CSTR(Root);
30112bd4897SEd Maste ENUM_TO_CSTR(String);
30212bd4897SEd Maste ENUM_TO_CSTR(Scope);
30312bd4897SEd Maste ENUM_TO_CSTR(Variable);
30412bd4897SEd Maste ENUM_TO_CSTR(VariableSynthetic);
30512bd4897SEd Maste ENUM_TO_CSTR(ScriptVariable);
30612bd4897SEd Maste ENUM_TO_CSTR(ScriptVariableSynthetic);
30712bd4897SEd Maste ENUM_TO_CSTR(AddressLoad);
30812bd4897SEd Maste ENUM_TO_CSTR(AddressFile);
30912bd4897SEd Maste ENUM_TO_CSTR(AddressLoadOrFile);
31012bd4897SEd Maste ENUM_TO_CSTR(ProcessID);
31112bd4897SEd Maste ENUM_TO_CSTR(ProcessFile);
31212bd4897SEd Maste ENUM_TO_CSTR(ScriptProcess);
31312bd4897SEd Maste ENUM_TO_CSTR(ThreadID);
31412bd4897SEd Maste ENUM_TO_CSTR(ThreadProtocolID);
31512bd4897SEd Maste ENUM_TO_CSTR(ThreadIndexID);
31612bd4897SEd Maste ENUM_TO_CSTR(ThreadName);
31712bd4897SEd Maste ENUM_TO_CSTR(ThreadQueue);
31812bd4897SEd Maste ENUM_TO_CSTR(ThreadStopReason);
319cfca06d7SDimitry Andric ENUM_TO_CSTR(ThreadStopReasonRaw);
32012bd4897SEd Maste ENUM_TO_CSTR(ThreadReturnValue);
32112bd4897SEd Maste ENUM_TO_CSTR(ThreadCompletedExpression);
32212bd4897SEd Maste ENUM_TO_CSTR(ScriptThread);
32312bd4897SEd Maste ENUM_TO_CSTR(ThreadInfo);
32412bd4897SEd Maste ENUM_TO_CSTR(TargetArch);
32512bd4897SEd Maste ENUM_TO_CSTR(ScriptTarget);
32612bd4897SEd Maste ENUM_TO_CSTR(ModuleFile);
32712bd4897SEd Maste ENUM_TO_CSTR(File);
3285e95aa85SEd Maste ENUM_TO_CSTR(Lang);
32912bd4897SEd Maste ENUM_TO_CSTR(FrameIndex);
33014f1b3e8SDimitry Andric ENUM_TO_CSTR(FrameNoDebug);
33112bd4897SEd Maste ENUM_TO_CSTR(FrameRegisterPC);
33212bd4897SEd Maste ENUM_TO_CSTR(FrameRegisterSP);
33312bd4897SEd Maste ENUM_TO_CSTR(FrameRegisterFP);
33412bd4897SEd Maste ENUM_TO_CSTR(FrameRegisterFlags);
33512bd4897SEd Maste ENUM_TO_CSTR(FrameRegisterByName);
33694994d37SDimitry Andric ENUM_TO_CSTR(FrameIsArtificial);
33712bd4897SEd Maste ENUM_TO_CSTR(ScriptFrame);
33812bd4897SEd Maste ENUM_TO_CSTR(FunctionID);
33912bd4897SEd Maste ENUM_TO_CSTR(FunctionDidChange);
34012bd4897SEd Maste ENUM_TO_CSTR(FunctionInitialFunction);
34112bd4897SEd Maste ENUM_TO_CSTR(FunctionName);
34212bd4897SEd Maste ENUM_TO_CSTR(FunctionNameWithArgs);
34312bd4897SEd Maste ENUM_TO_CSTR(FunctionNameNoArgs);
344706b4fc4SDimitry Andric ENUM_TO_CSTR(FunctionMangledName);
34512bd4897SEd Maste ENUM_TO_CSTR(FunctionAddrOffset);
34612bd4897SEd Maste ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
34712bd4897SEd Maste ENUM_TO_CSTR(FunctionLineOffset);
34812bd4897SEd Maste ENUM_TO_CSTR(FunctionPCOffset);
3495e95aa85SEd Maste ENUM_TO_CSTR(FunctionInitial);
3505e95aa85SEd Maste ENUM_TO_CSTR(FunctionChanged);
351e81d9d49SDimitry Andric ENUM_TO_CSTR(FunctionIsOptimized);
35212bd4897SEd Maste ENUM_TO_CSTR(LineEntryFile);
35312bd4897SEd Maste ENUM_TO_CSTR(LineEntryLineNumber);
35494994d37SDimitry Andric ENUM_TO_CSTR(LineEntryColumn);
35512bd4897SEd Maste ENUM_TO_CSTR(LineEntryStartAddress);
35612bd4897SEd Maste ENUM_TO_CSTR(LineEntryEndAddress);
35712bd4897SEd Maste ENUM_TO_CSTR(CurrentPCArrow);
35812bd4897SEd Maste }
35912bd4897SEd Maste return "???";
36012bd4897SEd Maste }
36112bd4897SEd Maste
36212bd4897SEd Maste #undef ENUM_TO_CSTR
36312bd4897SEd Maste
Dump(Stream & s,int depth) const36414f1b3e8SDimitry Andric void FormatEntity::Entry::Dump(Stream &s, int depth) const {
36512bd4897SEd Maste s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
36612bd4897SEd Maste if (fmt != eFormatDefault)
36712bd4897SEd Maste s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
36812bd4897SEd Maste if (!string.empty())
36912bd4897SEd Maste s.Printf("string = \"%s\"", string.c_str());
37012bd4897SEd Maste if (!printf_format.empty())
37112bd4897SEd Maste s.Printf("printf_format = \"%s\"", printf_format.c_str());
37212bd4897SEd Maste if (number != 0)
37312bd4897SEd Maste s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
37412bd4897SEd Maste if (deref)
37512bd4897SEd Maste s.Printf("deref = true, ");
37612bd4897SEd Maste s.EOL();
37714f1b3e8SDimitry Andric for (const auto &child : children) {
37812bd4897SEd Maste child.Dump(s, depth + 1);
37912bd4897SEd Maste }
38012bd4897SEd Maste }
38112bd4897SEd Maste
38212bd4897SEd Maste template <typename T>
RunScriptFormatKeyword(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,T t,const char * script_function_name)38314f1b3e8SDimitry Andric static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
38414f1b3e8SDimitry Andric const ExecutionContext *exe_ctx, T t,
38514f1b3e8SDimitry Andric const char *script_function_name) {
38612bd4897SEd Maste Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
38712bd4897SEd Maste
38814f1b3e8SDimitry Andric if (target) {
38914f1b3e8SDimitry Andric ScriptInterpreter *script_interpreter =
3905f29bb8aSDimitry Andric target->GetDebugger().GetScriptInterpreter();
39114f1b3e8SDimitry Andric if (script_interpreter) {
392b76161e4SDimitry Andric Status error;
39312bd4897SEd Maste std::string script_output;
39412bd4897SEd Maste
39514f1b3e8SDimitry Andric if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
39614f1b3e8SDimitry Andric script_output, error) &&
39714f1b3e8SDimitry Andric error.Success()) {
39812bd4897SEd Maste s.Printf("%s", script_output.c_str());
39912bd4897SEd Maste return true;
40014f1b3e8SDimitry Andric } else {
40112bd4897SEd Maste s.Printf("<error: %s>", error.AsCString());
40212bd4897SEd Maste }
40312bd4897SEd Maste }
40412bd4897SEd Maste }
40512bd4897SEd Maste return false;
40612bd4897SEd Maste }
40712bd4897SEd Maste
DumpAddressAndContent(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & addr,bool print_file_addr_or_load_addr)408706b4fc4SDimitry Andric static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc,
409706b4fc4SDimitry Andric const ExecutionContext *exe_ctx,
410706b4fc4SDimitry Andric const Address &addr,
41114f1b3e8SDimitry Andric bool print_file_addr_or_load_addr) {
41212bd4897SEd Maste Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
41312bd4897SEd Maste addr_t vaddr = LLDB_INVALID_ADDRESS;
41412bd4897SEd Maste if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
41512bd4897SEd Maste vaddr = addr.GetLoadAddress(target);
41612bd4897SEd Maste if (vaddr == LLDB_INVALID_ADDRESS)
41712bd4897SEd Maste vaddr = addr.GetFileAddress();
41812bd4897SEd Maste
41914f1b3e8SDimitry Andric if (vaddr != LLDB_INVALID_ADDRESS) {
42012bd4897SEd Maste int addr_width = 0;
42114f1b3e8SDimitry Andric if (exe_ctx && target) {
42212bd4897SEd Maste addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
42312bd4897SEd Maste }
42412bd4897SEd Maste if (addr_width == 0)
42512bd4897SEd Maste addr_width = 16;
42614f1b3e8SDimitry Andric if (print_file_addr_or_load_addr) {
427f3fbd1c0SDimitry Andric ExecutionContextScope *exe_scope = nullptr;
42812bd4897SEd Maste if (exe_ctx)
42912bd4897SEd Maste exe_scope = exe_ctx->GetBestExecutionContextScope();
43014f1b3e8SDimitry Andric addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
43114f1b3e8SDimitry Andric Address::DumpStyleModuleWithFileAddress, 0);
43214f1b3e8SDimitry Andric } else {
43312bd4897SEd Maste s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
43412bd4897SEd Maste }
43512bd4897SEd Maste return true;
43612bd4897SEd Maste }
43712bd4897SEd Maste return false;
43812bd4897SEd Maste }
43912bd4897SEd Maste
DumpAddressOffsetFromFunction(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & format_addr,bool concrete_only,bool no_padding,bool print_zero_offsets)44014f1b3e8SDimitry Andric static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
44112bd4897SEd Maste const ExecutionContext *exe_ctx,
44212bd4897SEd Maste const Address &format_addr,
44314f1b3e8SDimitry Andric bool concrete_only, bool no_padding,
44414f1b3e8SDimitry Andric bool print_zero_offsets) {
44514f1b3e8SDimitry Andric if (format_addr.IsValid()) {
44612bd4897SEd Maste Address func_addr;
44712bd4897SEd Maste
44814f1b3e8SDimitry Andric if (sc) {
44914f1b3e8SDimitry Andric if (sc->function) {
45012bd4897SEd Maste func_addr = sc->function->GetAddressRange().GetBaseAddress();
45114f1b3e8SDimitry Andric if (sc->block && !concrete_only) {
452f73363f1SDimitry Andric // Check to make sure we aren't in an inline function. If we are, use
453f73363f1SDimitry Andric // the inline block range that contains "format_addr" since blocks
454f73363f1SDimitry Andric // can be discontiguous.
45512bd4897SEd Maste Block *inline_block = sc->block->GetContainingInlinedBlock();
45612bd4897SEd Maste AddressRange inline_range;
4575f29bb8aSDimitry Andric if (inline_block && inline_block->GetRangeContainingAddress(
4585f29bb8aSDimitry Andric format_addr, inline_range))
45912bd4897SEd Maste func_addr = inline_range.GetBaseAddress();
46012bd4897SEd Maste }
46114f1b3e8SDimitry Andric } else if (sc->symbol && sc->symbol->ValueIsAddress())
4625e95aa85SEd Maste func_addr = sc->symbol->GetAddressRef();
46312bd4897SEd Maste }
46412bd4897SEd Maste
46514f1b3e8SDimitry Andric if (func_addr.IsValid()) {
46612bd4897SEd Maste const char *addr_offset_padding = no_padding ? "" : " ";
46712bd4897SEd Maste
46814f1b3e8SDimitry Andric if (func_addr.GetSection() == format_addr.GetSection()) {
46912bd4897SEd Maste addr_t func_file_addr = func_addr.GetFileAddress();
47012bd4897SEd Maste addr_t addr_file_addr = format_addr.GetFileAddress();
47114f1b3e8SDimitry Andric if (addr_file_addr > func_file_addr ||
47214f1b3e8SDimitry Andric (addr_file_addr == func_file_addr && print_zero_offsets)) {
47314f1b3e8SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
47414f1b3e8SDimitry Andric addr_file_addr - func_file_addr);
47514f1b3e8SDimitry Andric } else if (addr_file_addr < func_file_addr) {
47614f1b3e8SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
47714f1b3e8SDimitry Andric func_file_addr - addr_file_addr);
4785e95aa85SEd Maste }
47912bd4897SEd Maste return true;
48014f1b3e8SDimitry Andric } else {
48112bd4897SEd Maste Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
48214f1b3e8SDimitry Andric if (target) {
48312bd4897SEd Maste addr_t func_load_addr = func_addr.GetLoadAddress(target);
48412bd4897SEd Maste addr_t addr_load_addr = format_addr.GetLoadAddress(target);
48514f1b3e8SDimitry Andric if (addr_load_addr > func_load_addr ||
48614f1b3e8SDimitry Andric (addr_load_addr == func_load_addr && print_zero_offsets)) {
48714f1b3e8SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
48814f1b3e8SDimitry Andric addr_load_addr - func_load_addr);
48914f1b3e8SDimitry Andric } else if (addr_load_addr < func_load_addr) {
49014f1b3e8SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
49114f1b3e8SDimitry Andric func_load_addr - addr_load_addr);
4925e95aa85SEd Maste }
49312bd4897SEd Maste return true;
49412bd4897SEd Maste }
49512bd4897SEd Maste }
49612bd4897SEd Maste }
49712bd4897SEd Maste }
49812bd4897SEd Maste return false;
49912bd4897SEd Maste }
50012bd4897SEd Maste
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)50114f1b3e8SDimitry Andric static bool ScanBracketedRange(llvm::StringRef subpath,
50212bd4897SEd Maste size_t &close_bracket_index,
50312bd4897SEd Maste const char *&var_name_final_if_array_range,
50414f1b3e8SDimitry Andric int64_t &index_lower, int64_t &index_higher) {
505145449b1SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
50612bd4897SEd Maste close_bracket_index = llvm::StringRef::npos;
50712bd4897SEd Maste const size_t open_bracket_index = subpath.find('[');
50814f1b3e8SDimitry Andric if (open_bracket_index == llvm::StringRef::npos) {
509ead24645SDimitry Andric LLDB_LOGF(log,
510ead24645SDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
51112bd4897SEd Maste return false;
51212bd4897SEd Maste }
51312bd4897SEd Maste
51412bd4897SEd Maste close_bracket_index = subpath.find(']', open_bracket_index + 1);
51512bd4897SEd Maste
51614f1b3e8SDimitry Andric if (close_bracket_index == llvm::StringRef::npos) {
517ead24645SDimitry Andric LLDB_LOGF(log,
518ead24645SDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
51912bd4897SEd Maste return false;
52014f1b3e8SDimitry Andric } else {
52112bd4897SEd Maste var_name_final_if_array_range = subpath.data() + open_bracket_index;
52212bd4897SEd Maste
52314f1b3e8SDimitry Andric if (close_bracket_index - open_bracket_index == 1) {
524ead24645SDimitry Andric LLDB_LOGF(
525ead24645SDimitry Andric log,
52614f1b3e8SDimitry Andric "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
52712bd4897SEd Maste index_lower = 0;
52814f1b3e8SDimitry Andric } else {
52912bd4897SEd Maste const size_t separator_index = subpath.find('-', open_bracket_index + 1);
53012bd4897SEd Maste
53114f1b3e8SDimitry Andric if (separator_index == llvm::StringRef::npos) {
53212bd4897SEd Maste const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
533f3fbd1c0SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
53412bd4897SEd Maste index_higher = index_lower;
535ead24645SDimitry Andric LLDB_LOGF(log,
536ead24645SDimitry Andric "[ScanBracketedRange] [%" PRId64
53714f1b3e8SDimitry Andric "] detected, high index is same",
53814f1b3e8SDimitry Andric index_lower);
53914f1b3e8SDimitry Andric } else {
54012bd4897SEd Maste const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
54112bd4897SEd Maste const char *index_higher_cstr = subpath.data() + separator_index + 1;
542f3fbd1c0SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
543f3fbd1c0SDimitry Andric index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
544ead24645SDimitry Andric LLDB_LOGF(log,
545ead24645SDimitry Andric "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
54614f1b3e8SDimitry Andric index_lower, index_higher);
54712bd4897SEd Maste }
54814f1b3e8SDimitry Andric if (index_lower > index_higher && index_higher > 0) {
549ead24645SDimitry Andric LLDB_LOGF(log, "[ScanBracketedRange] swapping indices");
55012bd4897SEd Maste const int64_t temp = index_lower;
55112bd4897SEd Maste index_lower = index_higher;
55212bd4897SEd Maste index_higher = temp;
55312bd4897SEd Maste }
55412bd4897SEd Maste }
55512bd4897SEd Maste }
55612bd4897SEd Maste return true;
55712bd4897SEd Maste }
55812bd4897SEd Maste
DumpFile(Stream & s,const FileSpec & file,FileKind file_kind)55914f1b3e8SDimitry Andric static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
56014f1b3e8SDimitry Andric switch (file_kind) {
56112bd4897SEd Maste case FileKind::FileError:
56212bd4897SEd Maste break;
56312bd4897SEd Maste
56412bd4897SEd Maste case FileKind::Basename:
56514f1b3e8SDimitry Andric if (file.GetFilename()) {
56612bd4897SEd Maste s << file.GetFilename();
56712bd4897SEd Maste return true;
56812bd4897SEd Maste }
56912bd4897SEd Maste break;
57012bd4897SEd Maste
57112bd4897SEd Maste case FileKind::Dirname:
57214f1b3e8SDimitry Andric if (file.GetDirectory()) {
57312bd4897SEd Maste s << file.GetDirectory();
57412bd4897SEd Maste return true;
57512bd4897SEd Maste }
57612bd4897SEd Maste break;
57712bd4897SEd Maste
57812bd4897SEd Maste case FileKind::Fullpath:
57914f1b3e8SDimitry Andric if (file) {
58012bd4897SEd Maste s << file;
58112bd4897SEd Maste return true;
58212bd4897SEd Maste }
58312bd4897SEd Maste break;
58412bd4897SEd Maste }
58512bd4897SEd Maste return false;
58612bd4897SEd Maste }
58712bd4897SEd Maste
DumpRegister(Stream & s,StackFrame * frame,RegisterKind reg_kind,uint32_t reg_num,Format format)58814f1b3e8SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
589344a3780SDimitry Andric uint32_t reg_num, Format format) {
59014f1b3e8SDimitry Andric if (frame) {
59112bd4897SEd Maste RegisterContext *reg_ctx = frame->GetRegisterContext().get();
59212bd4897SEd Maste
59314f1b3e8SDimitry Andric if (reg_ctx) {
59414f1b3e8SDimitry Andric const uint32_t lldb_reg_num =
59514f1b3e8SDimitry Andric reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
59614f1b3e8SDimitry Andric if (lldb_reg_num != LLDB_INVALID_REGNUM) {
59714f1b3e8SDimitry Andric const RegisterInfo *reg_info =
59814f1b3e8SDimitry Andric reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
59914f1b3e8SDimitry Andric if (reg_info) {
60012bd4897SEd Maste RegisterValue reg_value;
60114f1b3e8SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
6027fa27ce4SDimitry Andric DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
60312bd4897SEd Maste return true;
60412bd4897SEd Maste }
60512bd4897SEd Maste }
60612bd4897SEd Maste }
60712bd4897SEd Maste }
60812bd4897SEd Maste }
60912bd4897SEd Maste return false;
61012bd4897SEd Maste }
61112bd4897SEd Maste
ExpandIndexedExpression(ValueObject * valobj,size_t index,bool deref_pointer)61214f1b3e8SDimitry Andric static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
61314f1b3e8SDimitry Andric bool deref_pointer) {
614145449b1SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
615e3b55780SDimitry Andric std::string name_to_deref = llvm::formatv("[{0}]", index);
616e3b55780SDimitry Andric LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref);
61712bd4897SEd Maste ValueObject::GetValueForExpressionPathOptions options;
61812bd4897SEd Maste ValueObject::ExpressionPathEndResultType final_value_type;
61912bd4897SEd Maste ValueObject::ExpressionPathScanEndReason reason_to_stop;
62014f1b3e8SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
62114f1b3e8SDimitry Andric (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
62214f1b3e8SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
62314f1b3e8SDimitry Andric ValueObjectSP item = valobj->GetValueForExpressionPath(
624e3b55780SDimitry Andric name_to_deref, &reason_to_stop, &final_value_type, options, &what_next);
62514f1b3e8SDimitry Andric if (!item) {
626ead24645SDimitry Andric LLDB_LOGF(log,
627ead24645SDimitry Andric "[ExpandIndexedExpression] ERROR: why stopping = %d,"
62812bd4897SEd Maste " final_value_type %d",
62914f1b3e8SDimitry Andric reason_to_stop, final_value_type);
63014f1b3e8SDimitry Andric } else {
631ead24645SDimitry Andric LLDB_LOGF(log,
632ead24645SDimitry Andric "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
63312bd4897SEd Maste " final_value_type %d",
63414f1b3e8SDimitry Andric reason_to_stop, final_value_type);
63512bd4897SEd Maste }
63612bd4897SEd Maste return item;
63712bd4897SEd Maste }
63812bd4897SEd Maste
ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)63914f1b3e8SDimitry Andric static char ConvertValueObjectStyleToChar(
64014f1b3e8SDimitry Andric ValueObject::ValueObjectRepresentationStyle style) {
64114f1b3e8SDimitry Andric switch (style) {
64214f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
64314f1b3e8SDimitry Andric return '@';
64414f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleValue:
64514f1b3e8SDimitry Andric return 'V';
64614f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLocation:
64714f1b3e8SDimitry Andric return 'L';
64814f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleSummary:
64914f1b3e8SDimitry Andric return 'S';
65014f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleChildrenCount:
65114f1b3e8SDimitry Andric return '#';
65214f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleType:
65314f1b3e8SDimitry Andric return 'T';
65414f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleName:
65514f1b3e8SDimitry Andric return 'N';
65614f1b3e8SDimitry Andric case ValueObject::eValueObjectRepresentationStyleExpressionPath:
65714f1b3e8SDimitry Andric return '>';
65812bd4897SEd Maste }
65912bd4897SEd Maste return '\0';
66012bd4897SEd Maste }
66112bd4897SEd Maste
662ac9a064cSDimitry Andric /// Options supported by format_provider<T> for integral arithmetic types.
663ac9a064cSDimitry Andric /// See table in FormatProviders.h.
664ac9a064cSDimitry Andric static llvm::Regex LLVMFormatPattern{"x[-+]?\\d*|n|d", llvm::Regex::IgnoreCase};
665ac9a064cSDimitry Andric
DumpValueWithLLVMFormat(Stream & s,llvm::StringRef options,ValueObject & valobj)666ac9a064cSDimitry Andric static bool DumpValueWithLLVMFormat(Stream &s, llvm::StringRef options,
667ac9a064cSDimitry Andric ValueObject &valobj) {
668ac9a064cSDimitry Andric std::string formatted;
669ac9a064cSDimitry Andric std::string llvm_format = ("{0:" + options + "}").str();
670ac9a064cSDimitry Andric
671ac9a064cSDimitry Andric auto type_info = valobj.GetTypeInfo();
672ac9a064cSDimitry Andric if ((type_info & eTypeIsInteger) && LLVMFormatPattern.match(options)) {
673ac9a064cSDimitry Andric if (type_info & eTypeIsSigned) {
674ac9a064cSDimitry Andric bool success = false;
675ac9a064cSDimitry Andric int64_t integer = valobj.GetValueAsSigned(0, &success);
676ac9a064cSDimitry Andric if (success)
677ac9a064cSDimitry Andric formatted = llvm::formatv(llvm_format.data(), integer);
678ac9a064cSDimitry Andric } else {
679ac9a064cSDimitry Andric bool success = false;
680ac9a064cSDimitry Andric uint64_t integer = valobj.GetValueAsUnsigned(0, &success);
681ac9a064cSDimitry Andric if (success)
682ac9a064cSDimitry Andric formatted = llvm::formatv(llvm_format.data(), integer);
683ac9a064cSDimitry Andric }
684ac9a064cSDimitry Andric }
685ac9a064cSDimitry Andric
686ac9a064cSDimitry Andric if (formatted.empty())
687ac9a064cSDimitry Andric return false;
688ac9a064cSDimitry Andric
689ac9a064cSDimitry Andric s.Write(formatted.data(), formatted.size());
690ac9a064cSDimitry Andric return true;
691ac9a064cSDimitry Andric }
692ac9a064cSDimitry Andric
DumpValue(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const FormatEntity::Entry & entry,ValueObject * valobj)69314f1b3e8SDimitry Andric static bool DumpValue(Stream &s, const SymbolContext *sc,
69412bd4897SEd Maste const ExecutionContext *exe_ctx,
69514f1b3e8SDimitry Andric const FormatEntity::Entry &entry, ValueObject *valobj) {
696f3fbd1c0SDimitry Andric if (valobj == nullptr)
69712bd4897SEd Maste return false;
69812bd4897SEd Maste
699145449b1SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
70012bd4897SEd Maste Format custom_format = eFormatInvalid;
70114f1b3e8SDimitry Andric ValueObject::ValueObjectRepresentationStyle val_obj_display =
70214f1b3e8SDimitry Andric entry.string.empty()
70314f1b3e8SDimitry Andric ? ValueObject::eValueObjectRepresentationStyleValue
70414f1b3e8SDimitry Andric : ValueObject::eValueObjectRepresentationStyleSummary;
70512bd4897SEd Maste
70612bd4897SEd Maste bool do_deref_pointer = entry.deref;
70712bd4897SEd Maste bool is_script = false;
70814f1b3e8SDimitry Andric switch (entry.type) {
70912bd4897SEd Maste case FormatEntity::Entry::Type::ScriptVariable:
71012bd4897SEd Maste is_script = true;
71112bd4897SEd Maste break;
71212bd4897SEd Maste
71312bd4897SEd Maste case FormatEntity::Entry::Type::Variable:
71412bd4897SEd Maste custom_format = entry.fmt;
71512bd4897SEd Maste val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
71612bd4897SEd Maste break;
71712bd4897SEd Maste
71812bd4897SEd Maste case FormatEntity::Entry::Type::ScriptVariableSynthetic:
71912bd4897SEd Maste is_script = true;
720e3b55780SDimitry Andric [[fallthrough]];
72112bd4897SEd Maste case FormatEntity::Entry::Type::VariableSynthetic:
72212bd4897SEd Maste custom_format = entry.fmt;
72312bd4897SEd Maste val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
72414f1b3e8SDimitry Andric if (!valobj->IsSynthetic()) {
72512bd4897SEd Maste valobj = valobj->GetSyntheticValue().get();
72612bd4897SEd Maste if (valobj == nullptr)
72712bd4897SEd Maste return false;
72812bd4897SEd Maste }
72912bd4897SEd Maste break;
73012bd4897SEd Maste
73112bd4897SEd Maste default:
73212bd4897SEd Maste return false;
73312bd4897SEd Maste }
73412bd4897SEd Maste
73514f1b3e8SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
73614f1b3e8SDimitry Andric (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
73714f1b3e8SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
73812bd4897SEd Maste ValueObject::GetValueForExpressionPathOptions options;
73914f1b3e8SDimitry Andric options.DontCheckDotVsArrowSyntax()
74014f1b3e8SDimitry Andric .DoAllowBitfieldSyntax()
74114f1b3e8SDimitry Andric .DoAllowFragileIVar()
74214f1b3e8SDimitry Andric .SetSyntheticChildrenTraversal(
74314f1b3e8SDimitry Andric ValueObject::GetValueForExpressionPathOptions::
74414f1b3e8SDimitry Andric SyntheticChildrenTraversal::Both);
745f3fbd1c0SDimitry Andric ValueObject *target = nullptr;
746f3fbd1c0SDimitry Andric const char *var_name_final_if_array_range = nullptr;
74712bd4897SEd Maste size_t close_bracket_index = llvm::StringRef::npos;
74812bd4897SEd Maste int64_t index_lower = -1;
74912bd4897SEd Maste int64_t index_higher = -1;
75012bd4897SEd Maste bool is_array_range = false;
75112bd4897SEd Maste bool was_plain_var = false;
75212bd4897SEd Maste bool was_var_format = false;
75312bd4897SEd Maste bool was_var_indexed = false;
75414f1b3e8SDimitry Andric ValueObject::ExpressionPathScanEndReason reason_to_stop =
75514f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString;
75614f1b3e8SDimitry Andric ValueObject::ExpressionPathEndResultType final_value_type =
75714f1b3e8SDimitry Andric ValueObject::eExpressionPathEndResultTypePlain;
75812bd4897SEd Maste
75914f1b3e8SDimitry Andric if (is_script) {
76012bd4897SEd Maste return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
76112bd4897SEd Maste }
76212bd4897SEd Maste
763ac9a064cSDimitry Andric auto split = llvm::StringRef(entry.string).split(':');
764ac9a064cSDimitry Andric auto subpath = split.first;
765ac9a064cSDimitry Andric auto llvm_format = split.second;
766ac9a064cSDimitry Andric
76712bd4897SEd Maste // simplest case ${var}, just print valobj's value
768ac9a064cSDimitry Andric if (subpath.empty()) {
76914f1b3e8SDimitry Andric if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
77014f1b3e8SDimitry Andric entry.number == ValueObject::eValueObjectRepresentationStyleValue)
77112bd4897SEd Maste was_plain_var = true;
77212bd4897SEd Maste else
77312bd4897SEd Maste was_var_format = true;
77412bd4897SEd Maste target = valobj;
77514f1b3e8SDimitry Andric } else // this is ${var.something} or multiple .something nested
77612bd4897SEd Maste {
777ac9a064cSDimitry Andric if (subpath[0] == '[')
77812bd4897SEd Maste was_var_indexed = true;
77914f1b3e8SDimitry Andric ScanBracketedRange(subpath, close_bracket_index,
78014f1b3e8SDimitry Andric var_name_final_if_array_range, index_lower,
78112bd4897SEd Maste index_higher);
78212bd4897SEd Maste
783b76161e4SDimitry Andric Status error;
78412bd4897SEd Maste
785ac9a064cSDimitry Andric LLDB_LOG(log, "[Debugger::FormatPrompt] symbol to expand: {0}", subpath);
78612bd4897SEd Maste
78714f1b3e8SDimitry Andric target =
78814f1b3e8SDimitry Andric valobj
789ac9a064cSDimitry Andric ->GetValueForExpressionPath(subpath, &reason_to_stop,
79014f1b3e8SDimitry Andric &final_value_type, options, &what_next)
79114f1b3e8SDimitry Andric .get();
79212bd4897SEd Maste
79314f1b3e8SDimitry Andric if (!target) {
794ead24645SDimitry Andric LLDB_LOGF(log,
795ead24645SDimitry Andric "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
79612bd4897SEd Maste " final_value_type %d",
79714f1b3e8SDimitry Andric reason_to_stop, final_value_type);
79812bd4897SEd Maste return false;
79914f1b3e8SDimitry Andric } else {
800ead24645SDimitry Andric LLDB_LOGF(log,
801ead24645SDimitry Andric "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
80212bd4897SEd Maste " final_value_type %d",
80314f1b3e8SDimitry Andric reason_to_stop, final_value_type);
80414f1b3e8SDimitry Andric target = target
80514f1b3e8SDimitry Andric ->GetQualifiedRepresentationIfAvailable(
80614f1b3e8SDimitry Andric target->GetDynamicValueType(), true)
80714f1b3e8SDimitry Andric .get();
80812bd4897SEd Maste }
80912bd4897SEd Maste }
81012bd4897SEd Maste
81114f1b3e8SDimitry Andric is_array_range =
81214f1b3e8SDimitry Andric (final_value_type ==
81314f1b3e8SDimitry Andric ValueObject::eExpressionPathEndResultTypeBoundedRange ||
81414f1b3e8SDimitry Andric final_value_type ==
81514f1b3e8SDimitry Andric ValueObject::eExpressionPathEndResultTypeUnboundedRange);
81612bd4897SEd Maste
81714f1b3e8SDimitry Andric do_deref_pointer =
81814f1b3e8SDimitry Andric (what_next == ValueObject::eExpressionPathAftermathDereference);
81912bd4897SEd Maste
82014f1b3e8SDimitry Andric if (do_deref_pointer && !is_array_range) {
82112bd4897SEd Maste // I have not deref-ed yet, let's do it
82214f1b3e8SDimitry Andric // this happens when we are not going through
823f73363f1SDimitry Andric // GetValueForVariableExpressionPath to get to the target ValueObject
824b76161e4SDimitry Andric Status error;
82512bd4897SEd Maste target = target->Dereference(error).get();
82614f1b3e8SDimitry Andric if (error.Fail()) {
827ead24645SDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
82814f1b3e8SDimitry Andric error.AsCString("unknown"));
82912bd4897SEd Maste return false;
83012bd4897SEd Maste }
83112bd4897SEd Maste do_deref_pointer = false;
83212bd4897SEd Maste }
83312bd4897SEd Maste
83414f1b3e8SDimitry Andric if (!target) {
835ead24645SDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
83614f1b3e8SDimitry Andric "prompt expression");
83712bd4897SEd Maste return false;
83812bd4897SEd Maste }
83912bd4897SEd Maste
840f73363f1SDimitry Andric // we do not want to use the summary for a bitfield of type T:n if we were
841f73363f1SDimitry Andric // originally dealing with just a T - that would get us into an endless
842f73363f1SDimitry Andric // recursion
84314f1b3e8SDimitry Andric if (target->IsBitfield() && was_var_indexed) {
84412bd4897SEd Maste // TODO: check for a (T:n)-specific summary - we should still obey that
84512bd4897SEd Maste StreamString bitfield_name;
84614f1b3e8SDimitry Andric bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
84714f1b3e8SDimitry Andric target->GetBitfieldBitSize());
84874a628f7SDimitry Andric auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
849e3b55780SDimitry Andric bitfield_name.GetString(), lldb::eFormatterMatchExact);
85014f1b3e8SDimitry Andric if (val_obj_display ==
85114f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary &&
85214f1b3e8SDimitry Andric !DataVisualization::GetSummaryForType(type_sp))
85312bd4897SEd Maste val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
85412bd4897SEd Maste }
85512bd4897SEd Maste
85612bd4897SEd Maste // TODO use flags for these
85714f1b3e8SDimitry Andric const uint32_t type_info_flags =
85814f1b3e8SDimitry Andric target->GetCompilerType().GetTypeInfo(nullptr);
85912bd4897SEd Maste bool is_array = (type_info_flags & eTypeIsArray) != 0;
86012bd4897SEd Maste bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
861e81d9d49SDimitry Andric bool is_aggregate = target->GetCompilerType().IsAggregateType();
86212bd4897SEd Maste
86314f1b3e8SDimitry Andric if ((is_array || is_pointer) && (!is_array_range) &&
86414f1b3e8SDimitry Andric val_obj_display ==
86514f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue) // this should be
86614f1b3e8SDimitry Andric // wrong, but there
86714f1b3e8SDimitry Andric // are some
86814f1b3e8SDimitry Andric // exceptions
86912bd4897SEd Maste {
87012bd4897SEd Maste StreamString str_temp;
871ead24645SDimitry Andric LLDB_LOGF(log,
87214f1b3e8SDimitry Andric "[Debugger::FormatPrompt] I am into array || pointer && !range");
87312bd4897SEd Maste
87414f1b3e8SDimitry Andric if (target->HasSpecialPrintableRepresentation(val_obj_display,
87514f1b3e8SDimitry Andric custom_format)) {
87612bd4897SEd Maste // try to use the special cases
87714f1b3e8SDimitry Andric bool success = target->DumpPrintableRepresentation(
87814f1b3e8SDimitry Andric str_temp, val_obj_display, custom_format);
879ead24645SDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
88014f1b3e8SDimitry Andric success ? "" : "n't");
88112bd4897SEd Maste
88212bd4897SEd Maste // should not happen
88312bd4897SEd Maste if (success)
88414f1b3e8SDimitry Andric s << str_temp.GetString();
88512bd4897SEd Maste return true;
88614f1b3e8SDimitry Andric } else {
88712bd4897SEd Maste if (was_plain_var) // if ${var}
88812bd4897SEd Maste {
88912bd4897SEd Maste s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
89014f1b3e8SDimitry Andric } else if (is_pointer) // if pointer, value is the address stored
89112bd4897SEd Maste {
89214f1b3e8SDimitry Andric target->DumpPrintableRepresentation(
89314f1b3e8SDimitry Andric s, val_obj_display, custom_format,
89414f1b3e8SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eDisable);
89512bd4897SEd Maste }
89612bd4897SEd Maste return true;
89712bd4897SEd Maste }
89812bd4897SEd Maste }
89912bd4897SEd Maste
90014f1b3e8SDimitry Andric // if directly trying to print ${var}, and this is an aggregate, display a
901f73363f1SDimitry Andric // nice type @ location message
90214f1b3e8SDimitry Andric if (is_aggregate && was_plain_var) {
90312bd4897SEd Maste s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
90412bd4897SEd Maste return true;
90512bd4897SEd Maste }
90612bd4897SEd Maste
90714f1b3e8SDimitry Andric // if directly trying to print ${var%V}, and this is an aggregate, do not let
90814f1b3e8SDimitry Andric // the user do it
90914f1b3e8SDimitry Andric if (is_aggregate &&
91014f1b3e8SDimitry Andric ((was_var_format &&
91114f1b3e8SDimitry Andric val_obj_display ==
91214f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue))) {
91312bd4897SEd Maste s << "<invalid use of aggregate type>";
91412bd4897SEd Maste return true;
91512bd4897SEd Maste }
91612bd4897SEd Maste
91714f1b3e8SDimitry Andric if (!is_array_range) {
918ac9a064cSDimitry Andric if (!llvm_format.empty()) {
919ac9a064cSDimitry Andric if (DumpValueWithLLVMFormat(s, llvm_format, *target)) {
920ac9a064cSDimitry Andric LLDB_LOGF(log, "dumping using llvm format");
921ac9a064cSDimitry Andric return true;
922ac9a064cSDimitry Andric } else {
923ac9a064cSDimitry Andric LLDB_LOG(
924ac9a064cSDimitry Andric log,
925ac9a064cSDimitry Andric "empty output using llvm format '{0}' - with type info flags {1}",
926ac9a064cSDimitry Andric entry.printf_format, target->GetTypeInfo());
927ac9a064cSDimitry Andric }
928ac9a064cSDimitry Andric }
929ac9a064cSDimitry Andric LLDB_LOGF(log, "dumping ordinary printable output");
93014f1b3e8SDimitry Andric return target->DumpPrintableRepresentation(s, val_obj_display,
93114f1b3e8SDimitry Andric custom_format);
93214f1b3e8SDimitry Andric } else {
933ead24645SDimitry Andric LLDB_LOGF(log,
934ead24645SDimitry Andric "[Debugger::FormatPrompt] checking if I can handle as array");
93512bd4897SEd Maste if (!is_array && !is_pointer)
93612bd4897SEd Maste return false;
937ead24645SDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
9385e95aa85SEd Maste StreamString special_directions_stream;
93912bd4897SEd Maste llvm::StringRef special_directions;
94014f1b3e8SDimitry Andric if (close_bracket_index != llvm::StringRef::npos &&
94114f1b3e8SDimitry Andric subpath.size() > close_bracket_index) {
94212bd4897SEd Maste ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
94314f1b3e8SDimitry Andric special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
94412bd4897SEd Maste additional_data.GetCString());
94512bd4897SEd Maste
94614f1b3e8SDimitry Andric if (entry.fmt != eFormatDefault) {
94714f1b3e8SDimitry Andric const char format_char =
94814f1b3e8SDimitry Andric FormatManager::GetFormatAsFormatChar(entry.fmt);
94912bd4897SEd Maste if (format_char != '\0')
95012bd4897SEd Maste special_directions_stream.Printf("%%%c", format_char);
95114f1b3e8SDimitry Andric else {
95214f1b3e8SDimitry Andric const char *format_cstr =
95314f1b3e8SDimitry Andric FormatManager::GetFormatAsCString(entry.fmt);
95412bd4897SEd Maste special_directions_stream.Printf("%%%s", format_cstr);
95512bd4897SEd Maste }
95614f1b3e8SDimitry Andric } else if (entry.number != 0) {
95714f1b3e8SDimitry Andric const char style_char = ConvertValueObjectStyleToChar(
95814f1b3e8SDimitry Andric (ValueObject::ValueObjectRepresentationStyle)entry.number);
95912bd4897SEd Maste if (style_char)
96012bd4897SEd Maste special_directions_stream.Printf("%%%c", style_char);
96112bd4897SEd Maste }
96212bd4897SEd Maste special_directions_stream.PutChar('}');
96314f1b3e8SDimitry Andric special_directions =
96414f1b3e8SDimitry Andric llvm::StringRef(special_directions_stream.GetString());
96512bd4897SEd Maste }
96612bd4897SEd Maste
96712bd4897SEd Maste // let us display items index_lower thru index_higher of this array
96812bd4897SEd Maste s.PutChar('[');
96912bd4897SEd Maste
97012bd4897SEd Maste if (index_higher < 0)
971ac9a064cSDimitry Andric index_higher = valobj->GetNumChildrenIgnoringErrors() - 1;
97212bd4897SEd Maste
97314f1b3e8SDimitry Andric uint32_t max_num_children =
97414f1b3e8SDimitry Andric target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
97512bd4897SEd Maste
97612bd4897SEd Maste bool success = true;
97714f1b3e8SDimitry Andric for (int64_t index = index_lower; index <= index_higher; ++index) {
978344a3780SDimitry Andric ValueObject *item = ExpandIndexedExpression(target, index, false).get();
97912bd4897SEd Maste
98014f1b3e8SDimitry Andric if (!item) {
981ead24645SDimitry Andric LLDB_LOGF(log,
982ead24645SDimitry Andric "[Debugger::FormatPrompt] ERROR in getting child item at "
98314f1b3e8SDimitry Andric "index %" PRId64,
98414f1b3e8SDimitry Andric index);
98514f1b3e8SDimitry Andric } else {
986ead24645SDimitry Andric LLDB_LOGF(
987ead24645SDimitry Andric log,
98814f1b3e8SDimitry Andric "[Debugger::FormatPrompt] special_directions for child item: %s",
98914f1b3e8SDimitry Andric special_directions.data() ? special_directions.data() : "");
99012bd4897SEd Maste }
99112bd4897SEd Maste
99214f1b3e8SDimitry Andric if (special_directions.empty()) {
99314f1b3e8SDimitry Andric success &= item->DumpPrintableRepresentation(s, val_obj_display,
99414f1b3e8SDimitry Andric custom_format);
99514f1b3e8SDimitry Andric } else {
99614f1b3e8SDimitry Andric success &= FormatEntity::FormatStringRef(
99714f1b3e8SDimitry Andric special_directions, s, sc, exe_ctx, nullptr, item, false, false);
99812bd4897SEd Maste }
99912bd4897SEd Maste
100014f1b3e8SDimitry Andric if (--max_num_children == 0) {
100112bd4897SEd Maste s.PutCString(", ...");
100212bd4897SEd Maste break;
100312bd4897SEd Maste }
100412bd4897SEd Maste
100512bd4897SEd Maste if (index < index_higher)
100612bd4897SEd Maste s.PutChar(',');
100712bd4897SEd Maste }
100812bd4897SEd Maste s.PutChar(']');
100912bd4897SEd Maste return success;
101012bd4897SEd Maste }
101112bd4897SEd Maste }
101212bd4897SEd Maste
DumpRegister(Stream & s,StackFrame * frame,const char * reg_name,Format format)101314f1b3e8SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
101414f1b3e8SDimitry Andric Format format) {
101514f1b3e8SDimitry Andric if (frame) {
101612bd4897SEd Maste RegisterContext *reg_ctx = frame->GetRegisterContext().get();
101712bd4897SEd Maste
101814f1b3e8SDimitry Andric if (reg_ctx) {
101912bd4897SEd Maste const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
102014f1b3e8SDimitry Andric if (reg_info) {
102112bd4897SEd Maste RegisterValue reg_value;
102214f1b3e8SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
10237fa27ce4SDimitry Andric DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
102412bd4897SEd Maste return true;
102512bd4897SEd Maste }
102612bd4897SEd Maste }
102712bd4897SEd Maste }
102812bd4897SEd Maste }
102912bd4897SEd Maste return false;
103012bd4897SEd Maste }
103112bd4897SEd Maste
FormatThreadExtendedInfoRecurse(const FormatEntity::Entry & entry,const StructuredData::ObjectSP & thread_info_dictionary,const SymbolContext * sc,const ExecutionContext * exe_ctx,Stream & s)103214f1b3e8SDimitry Andric static bool FormatThreadExtendedInfoRecurse(
103314f1b3e8SDimitry Andric const FormatEntity::Entry &entry,
103412bd4897SEd Maste const StructuredData::ObjectSP &thread_info_dictionary,
103514f1b3e8SDimitry Andric const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
103612bd4897SEd Maste llvm::StringRef path(entry.string);
103712bd4897SEd Maste
103814f1b3e8SDimitry Andric StructuredData::ObjectSP value =
103914f1b3e8SDimitry Andric thread_info_dictionary->GetObjectForDotSeparatedPath(path);
104012bd4897SEd Maste
104114f1b3e8SDimitry Andric if (value) {
104261b440f5SDimitry Andric if (value->GetType() == eStructuredDataTypeInteger) {
104312bd4897SEd Maste const char *token_format = "0x%4.4" PRIx64;
104412bd4897SEd Maste if (!entry.printf_format.empty())
104512bd4897SEd Maste token_format = entry.printf_format.c_str();
10467fa27ce4SDimitry Andric s.Printf(token_format, value->GetUnsignedIntegerValue());
104712bd4897SEd Maste return true;
104861b440f5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeFloat) {
104912bd4897SEd Maste s.Printf("%f", value->GetAsFloat()->GetValue());
105012bd4897SEd Maste return true;
105161b440f5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeString) {
1052b76161e4SDimitry Andric s.Format("{0}", value->GetAsString()->GetValue());
105312bd4897SEd Maste return true;
105461b440f5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeArray) {
105514f1b3e8SDimitry Andric if (value->GetAsArray()->GetSize() > 0) {
105612bd4897SEd Maste s.Printf("%zu", value->GetAsArray()->GetSize());
105712bd4897SEd Maste return true;
105812bd4897SEd Maste }
105961b440f5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeDictionary) {
106014f1b3e8SDimitry Andric s.Printf("%zu",
106114f1b3e8SDimitry Andric value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
106212bd4897SEd Maste return true;
106312bd4897SEd Maste }
106412bd4897SEd Maste }
106512bd4897SEd Maste
106612bd4897SEd Maste return false;
106712bd4897SEd Maste }
106812bd4897SEd Maste
IsToken(const char * var_name_begin,const char * var)106914f1b3e8SDimitry Andric static inline bool IsToken(const char *var_name_begin, const char *var) {
107012bd4897SEd Maste return (::strncmp(var_name_begin, var, strlen(var)) == 0);
107112bd4897SEd Maste }
107212bd4897SEd Maste
1073e3b55780SDimitry Andric /// Parses the basename out of a demangled function name
1074e3b55780SDimitry Andric /// that may include function arguments. Supports
1075e3b55780SDimitry Andric /// template functions.
1076e3b55780SDimitry Andric ///
1077e3b55780SDimitry Andric /// Returns pointers to the opening and closing parenthesis of
1078e3b55780SDimitry Andric /// `full_name`. Can return nullptr for either parenthesis if
1079e3b55780SDimitry Andric /// none is exists.
1080e3b55780SDimitry Andric static std::pair<char const *, char const *>
ParseBaseName(char const * full_name)1081e3b55780SDimitry Andric ParseBaseName(char const *full_name) {
1082e3b55780SDimitry Andric const char *open_paren = strchr(full_name, '(');
1083e3b55780SDimitry Andric const char *close_paren = nullptr;
1084e3b55780SDimitry Andric const char *generic = strchr(full_name, '<');
1085e3b55780SDimitry Andric // if before the arguments list begins there is a template sign
1086e3b55780SDimitry Andric // then scan to the end of the generic args before you try to find
1087e3b55780SDimitry Andric // the arguments list
1088e3b55780SDimitry Andric if (generic && open_paren && generic < open_paren) {
1089e3b55780SDimitry Andric int generic_depth = 1;
1090e3b55780SDimitry Andric ++generic;
1091e3b55780SDimitry Andric for (; *generic && generic_depth > 0; generic++) {
1092e3b55780SDimitry Andric if (*generic == '<')
1093e3b55780SDimitry Andric generic_depth++;
1094e3b55780SDimitry Andric if (*generic == '>')
1095e3b55780SDimitry Andric generic_depth--;
1096e3b55780SDimitry Andric }
1097e3b55780SDimitry Andric if (*generic)
1098e3b55780SDimitry Andric open_paren = strchr(generic, '(');
1099e3b55780SDimitry Andric else
1100e3b55780SDimitry Andric open_paren = nullptr;
1101e3b55780SDimitry Andric }
1102e3b55780SDimitry Andric
1103e3b55780SDimitry Andric if (open_paren) {
1104e3b55780SDimitry Andric if (IsToken(open_paren, "(anonymous namespace)")) {
1105e3b55780SDimitry Andric open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1106e3b55780SDimitry Andric if (open_paren)
1107e3b55780SDimitry Andric close_paren = strchr(open_paren, ')');
1108e3b55780SDimitry Andric } else
1109e3b55780SDimitry Andric close_paren = strchr(open_paren, ')');
1110e3b55780SDimitry Andric }
1111e3b55780SDimitry Andric
1112e3b55780SDimitry Andric return {open_paren, close_paren};
1113e3b55780SDimitry Andric }
1114e3b55780SDimitry Andric
1115e3b55780SDimitry Andric /// Writes out the function name in 'full_name' to 'out_stream'
1116e3b55780SDimitry Andric /// but replaces each argument type with the variable name
1117e3b55780SDimitry Andric /// and the corresponding pretty-printed value
PrettyPrintFunctionNameWithArgs(Stream & out_stream,char const * full_name,ExecutionContextScope * exe_scope,VariableList const & args)1118e3b55780SDimitry Andric static void PrettyPrintFunctionNameWithArgs(Stream &out_stream,
1119e3b55780SDimitry Andric char const *full_name,
1120e3b55780SDimitry Andric ExecutionContextScope *exe_scope,
1121e3b55780SDimitry Andric VariableList const &args) {
1122e3b55780SDimitry Andric auto [open_paren, close_paren] = ParseBaseName(full_name);
1123e3b55780SDimitry Andric if (open_paren)
1124e3b55780SDimitry Andric out_stream.Write(full_name, open_paren - full_name + 1);
1125e3b55780SDimitry Andric else {
1126e3b55780SDimitry Andric out_stream.PutCString(full_name);
1127e3b55780SDimitry Andric out_stream.PutChar('(');
1128e3b55780SDimitry Andric }
1129e3b55780SDimitry Andric
1130e3b55780SDimitry Andric FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1131e3b55780SDimitry Andric
1132e3b55780SDimitry Andric if (close_paren)
1133e3b55780SDimitry Andric out_stream.PutCString(close_paren);
1134e3b55780SDimitry Andric else
1135e3b55780SDimitry Andric out_stream.PutChar(')');
1136e3b55780SDimitry Andric }
1137e3b55780SDimitry Andric
FormatInlinedBlock(Stream & out_stream,Block * block)11384df029ccSDimitry Andric static void FormatInlinedBlock(Stream &out_stream, Block *block) {
11394df029ccSDimitry Andric if (!block)
11404df029ccSDimitry Andric return;
11414df029ccSDimitry Andric Block *inline_block = block->GetContainingInlinedBlock();
11424df029ccSDimitry Andric if (inline_block) {
11434df029ccSDimitry Andric if (const InlineFunctionInfo *inline_info =
11444df029ccSDimitry Andric inline_block->GetInlinedFunctionInfo()) {
11454df029ccSDimitry Andric out_stream.PutCString(" [inlined] ");
11464df029ccSDimitry Andric inline_info->GetName().Dump(&out_stream);
11474df029ccSDimitry Andric }
11484df029ccSDimitry Andric }
11494df029ccSDimitry Andric }
11504df029ccSDimitry 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)115114f1b3e8SDimitry Andric bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
115212bd4897SEd Maste const SymbolContext *sc,
115312bd4897SEd Maste const ExecutionContext *exe_ctx,
115414f1b3e8SDimitry Andric const Address *addr, ValueObject *valobj,
115512bd4897SEd Maste bool function_changed,
115614f1b3e8SDimitry Andric bool initial_function) {
115714f1b3e8SDimitry Andric if (!format_str.empty()) {
115812bd4897SEd Maste FormatEntity::Entry root;
1159b76161e4SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
116014f1b3e8SDimitry Andric if (error.Success()) {
116114f1b3e8SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
116214f1b3e8SDimitry Andric function_changed, initial_function);
116312bd4897SEd Maste }
116412bd4897SEd Maste }
116512bd4897SEd Maste return false;
116612bd4897SEd Maste }
1167f3fbd1c0SDimitry 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)116814f1b3e8SDimitry Andric bool FormatEntity::FormatCString(const char *format, Stream &s,
116912bd4897SEd Maste const SymbolContext *sc,
117012bd4897SEd Maste const ExecutionContext *exe_ctx,
117114f1b3e8SDimitry Andric const Address *addr, ValueObject *valobj,
117214f1b3e8SDimitry Andric bool function_changed, bool initial_function) {
117314f1b3e8SDimitry Andric if (format && format[0]) {
117412bd4897SEd Maste FormatEntity::Entry root;
117512bd4897SEd Maste llvm::StringRef format_str(format);
1176b76161e4SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
117714f1b3e8SDimitry Andric if (error.Success()) {
117814f1b3e8SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
117914f1b3e8SDimitry Andric function_changed, initial_function);
118012bd4897SEd Maste }
118112bd4897SEd Maste }
118212bd4897SEd Maste return false;
118312bd4897SEd Maste }
118412bd4897SEd Maste
Format(const Entry & entry,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)118514f1b3e8SDimitry Andric bool FormatEntity::Format(const Entry &entry, Stream &s,
118612bd4897SEd Maste const SymbolContext *sc,
118714f1b3e8SDimitry Andric const ExecutionContext *exe_ctx, const Address *addr,
118814f1b3e8SDimitry Andric ValueObject *valobj, bool function_changed,
118914f1b3e8SDimitry Andric bool initial_function) {
119014f1b3e8SDimitry Andric switch (entry.type) {
119112bd4897SEd Maste case Entry::Type::Invalid:
119214f1b3e8SDimitry Andric case Entry::Type::ParentNumber: // Only used for
119314f1b3e8SDimitry Andric // FormatEntity::Entry::Definition encoding
119414f1b3e8SDimitry Andric case Entry::Type::ParentString: // Only used for
119514f1b3e8SDimitry Andric // FormatEntity::Entry::Definition encoding
119612bd4897SEd Maste return false;
11975f29bb8aSDimitry Andric case Entry::Type::EscapeCode:
11985f29bb8aSDimitry Andric if (exe_ctx) {
11995f29bb8aSDimitry Andric if (Target *target = exe_ctx->GetTargetPtr()) {
12005f29bb8aSDimitry Andric Debugger &debugger = target->GetDebugger();
12015f29bb8aSDimitry Andric if (debugger.GetUseColor()) {
12025f29bb8aSDimitry Andric s.PutCString(entry.string);
12035f29bb8aSDimitry Andric }
12045f29bb8aSDimitry Andric }
12055f29bb8aSDimitry Andric }
12065f29bb8aSDimitry Andric // Always return true, so colors being disabled is transparent.
12075f29bb8aSDimitry Andric return true;
120812bd4897SEd Maste
120912bd4897SEd Maste case Entry::Type::Root:
121014f1b3e8SDimitry Andric for (const auto &child : entry.children) {
121114f1b3e8SDimitry Andric if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
121214f1b3e8SDimitry Andric initial_function)) {
121312bd4897SEd Maste return false; // If any item of root fails, then the formatting fails
121412bd4897SEd Maste }
121512bd4897SEd Maste }
121612bd4897SEd Maste return true; // Only return true if all items succeeded
121712bd4897SEd Maste
121812bd4897SEd Maste case Entry::Type::String:
121914f1b3e8SDimitry Andric s.PutCString(entry.string);
122012bd4897SEd Maste return true;
122112bd4897SEd Maste
122214f1b3e8SDimitry Andric case Entry::Type::Scope: {
122312bd4897SEd Maste StreamString scope_stream;
122412bd4897SEd Maste bool success = false;
122514f1b3e8SDimitry Andric for (const auto &child : entry.children) {
122614f1b3e8SDimitry Andric success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
122714f1b3e8SDimitry Andric function_changed, initial_function);
122812bd4897SEd Maste if (!success)
122912bd4897SEd Maste break;
123012bd4897SEd Maste }
1231f73363f1SDimitry Andric // Only if all items in a scope succeed, then do we print the output into
1232f73363f1SDimitry Andric // the main stream
123312bd4897SEd Maste if (success)
123412bd4897SEd Maste s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
123512bd4897SEd Maste }
123612bd4897SEd Maste return true; // Scopes always successfully print themselves
123712bd4897SEd Maste
123812bd4897SEd Maste case Entry::Type::Variable:
123912bd4897SEd Maste case Entry::Type::VariableSynthetic:
124012bd4897SEd Maste case Entry::Type::ScriptVariable:
124112bd4897SEd Maste case Entry::Type::ScriptVariableSynthetic:
1242f3fbd1c0SDimitry Andric return DumpValue(s, sc, exe_ctx, entry, valobj);
124312bd4897SEd Maste
124412bd4897SEd Maste case Entry::Type::AddressFile:
124512bd4897SEd Maste case Entry::Type::AddressLoad:
124612bd4897SEd Maste case Entry::Type::AddressLoadOrFile:
1247706b4fc4SDimitry Andric return (
1248706b4fc4SDimitry Andric addr != nullptr && addr->IsValid() &&
1249706b4fc4SDimitry Andric DumpAddressAndContent(s, sc, exe_ctx, *addr,
125014f1b3e8SDimitry Andric entry.type == Entry::Type::AddressLoadOrFile));
125112bd4897SEd Maste
125212bd4897SEd Maste case Entry::Type::ProcessID:
125314f1b3e8SDimitry Andric if (exe_ctx) {
125412bd4897SEd Maste Process *process = exe_ctx->GetProcessPtr();
125514f1b3e8SDimitry Andric if (process) {
125612bd4897SEd Maste const char *format = "%" PRIu64;
125712bd4897SEd Maste if (!entry.printf_format.empty())
125812bd4897SEd Maste format = entry.printf_format.c_str();
125912bd4897SEd Maste s.Printf(format, process->GetID());
126012bd4897SEd Maste return true;
126112bd4897SEd Maste }
126212bd4897SEd Maste }
126312bd4897SEd Maste return false;
126412bd4897SEd Maste
126512bd4897SEd Maste case Entry::Type::ProcessFile:
126614f1b3e8SDimitry Andric if (exe_ctx) {
126712bd4897SEd Maste Process *process = exe_ctx->GetProcessPtr();
126814f1b3e8SDimitry Andric if (process) {
126912bd4897SEd Maste Module *exe_module = process->GetTarget().GetExecutableModulePointer();
127014f1b3e8SDimitry Andric if (exe_module) {
127112bd4897SEd Maste if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
127212bd4897SEd Maste return true;
127312bd4897SEd Maste }
127412bd4897SEd Maste }
127512bd4897SEd Maste }
127612bd4897SEd Maste return false;
127712bd4897SEd Maste
127812bd4897SEd Maste case Entry::Type::ScriptProcess:
127914f1b3e8SDimitry Andric if (exe_ctx) {
128012bd4897SEd Maste Process *process = exe_ctx->GetProcessPtr();
128112bd4897SEd Maste if (process)
128214f1b3e8SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, process,
128314f1b3e8SDimitry Andric entry.string.c_str());
128412bd4897SEd Maste }
128512bd4897SEd Maste return false;
128612bd4897SEd Maste
128712bd4897SEd Maste case Entry::Type::ThreadID:
128814f1b3e8SDimitry Andric if (exe_ctx) {
128912bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
129014f1b3e8SDimitry Andric if (thread) {
129112bd4897SEd Maste const char *format = "0x%4.4" PRIx64;
129214f1b3e8SDimitry Andric if (!entry.printf_format.empty()) {
129312bd4897SEd Maste // Watch for the special "tid" format...
129414f1b3e8SDimitry Andric if (entry.printf_format == "tid") {
129514f1b3e8SDimitry Andric // TODO(zturner): Rather than hardcoding this to be platform
1296f73363f1SDimitry Andric // specific, it should be controlled by a setting and the default
1297f73363f1SDimitry Andric // value of the setting can be different depending on the platform.
129812bd4897SEd Maste Target &target = thread->GetProcess()->GetTarget();
129912bd4897SEd Maste ArchSpec arch(target.GetArchitecture());
130014f1b3e8SDimitry Andric llvm::Triple::OSType ostype = arch.IsValid()
130114f1b3e8SDimitry Andric ? arch.GetTriple().getOS()
130214f1b3e8SDimitry Andric : llvm::Triple::UnknownOS;
1303b1c73532SDimitry Andric if (ostype == llvm::Triple::FreeBSD ||
1304b1c73532SDimitry Andric ostype == llvm::Triple::Linux ||
1305b1c73532SDimitry Andric ostype == llvm::Triple::NetBSD ||
1306b1c73532SDimitry Andric ostype == llvm::Triple::OpenBSD) {
130712bd4897SEd Maste format = "%" PRIu64;
130812bd4897SEd Maste }
130914f1b3e8SDimitry Andric } else {
131012bd4897SEd Maste format = entry.printf_format.c_str();
131112bd4897SEd Maste }
131212bd4897SEd Maste }
131312bd4897SEd Maste s.Printf(format, thread->GetID());
131412bd4897SEd Maste return true;
131512bd4897SEd Maste }
131612bd4897SEd Maste }
131712bd4897SEd Maste return false;
131812bd4897SEd Maste
131912bd4897SEd Maste case Entry::Type::ThreadProtocolID:
132014f1b3e8SDimitry Andric if (exe_ctx) {
132112bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
132214f1b3e8SDimitry Andric if (thread) {
132312bd4897SEd Maste const char *format = "0x%4.4" PRIx64;
132412bd4897SEd Maste if (!entry.printf_format.empty())
132512bd4897SEd Maste format = entry.printf_format.c_str();
132612bd4897SEd Maste s.Printf(format, thread->GetProtocolID());
132712bd4897SEd Maste return true;
132812bd4897SEd Maste }
132912bd4897SEd Maste }
133012bd4897SEd Maste return false;
133112bd4897SEd Maste
133212bd4897SEd Maste case Entry::Type::ThreadIndexID:
133314f1b3e8SDimitry Andric if (exe_ctx) {
133412bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
133514f1b3e8SDimitry Andric if (thread) {
133612bd4897SEd Maste const char *format = "%" PRIu32;
133712bd4897SEd Maste if (!entry.printf_format.empty())
133812bd4897SEd Maste format = entry.printf_format.c_str();
133912bd4897SEd Maste s.Printf(format, thread->GetIndexID());
134012bd4897SEd Maste return true;
134112bd4897SEd Maste }
134212bd4897SEd Maste }
134312bd4897SEd Maste return false;
134412bd4897SEd Maste
134512bd4897SEd Maste case Entry::Type::ThreadName:
134614f1b3e8SDimitry Andric if (exe_ctx) {
134712bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
134814f1b3e8SDimitry Andric if (thread) {
134912bd4897SEd Maste const char *cstr = thread->GetName();
135014f1b3e8SDimitry Andric if (cstr && cstr[0]) {
135112bd4897SEd Maste s.PutCString(cstr);
135212bd4897SEd Maste return true;
135312bd4897SEd Maste }
135412bd4897SEd Maste }
135512bd4897SEd Maste }
135612bd4897SEd Maste return false;
135712bd4897SEd Maste
135812bd4897SEd Maste case Entry::Type::ThreadQueue:
135914f1b3e8SDimitry Andric if (exe_ctx) {
136012bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
136114f1b3e8SDimitry Andric if (thread) {
136212bd4897SEd Maste const char *cstr = thread->GetQueueName();
136314f1b3e8SDimitry Andric if (cstr && cstr[0]) {
136412bd4897SEd Maste s.PutCString(cstr);
136512bd4897SEd Maste return true;
136612bd4897SEd Maste }
136712bd4897SEd Maste }
136812bd4897SEd Maste }
136912bd4897SEd Maste return false;
137012bd4897SEd Maste
137112bd4897SEd Maste case Entry::Type::ThreadStopReason:
137214f1b3e8SDimitry Andric if (exe_ctx) {
1373cfca06d7SDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
1374cfca06d7SDimitry Andric std::string stop_description = thread->GetStopDescription();
1375cfca06d7SDimitry Andric if (!stop_description.empty()) {
1376cfca06d7SDimitry Andric s.PutCString(stop_description);
137712bd4897SEd Maste return true;
137812bd4897SEd Maste }
137912bd4897SEd Maste }
138012bd4897SEd Maste }
1381cfca06d7SDimitry Andric return false;
1382cfca06d7SDimitry Andric
1383cfca06d7SDimitry Andric case Entry::Type::ThreadStopReasonRaw:
1384cfca06d7SDimitry Andric if (exe_ctx) {
1385cfca06d7SDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
1386cfca06d7SDimitry Andric std::string stop_description = thread->GetStopDescriptionRaw();
1387cfca06d7SDimitry Andric if (!stop_description.empty()) {
1388cfca06d7SDimitry Andric s.PutCString(stop_description);
1389cfca06d7SDimitry Andric return true;
1390cfca06d7SDimitry Andric }
1391cfca06d7SDimitry Andric }
139212bd4897SEd Maste }
139312bd4897SEd Maste return false;
139412bd4897SEd Maste
139512bd4897SEd Maste case Entry::Type::ThreadReturnValue:
139614f1b3e8SDimitry Andric if (exe_ctx) {
139712bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
139814f1b3e8SDimitry Andric if (thread) {
139912bd4897SEd Maste StopInfoSP stop_info_sp = thread->GetStopInfo();
140014f1b3e8SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
140114f1b3e8SDimitry Andric ValueObjectSP return_valobj_sp =
140214f1b3e8SDimitry Andric StopInfo::GetReturnValueObject(stop_info_sp);
140314f1b3e8SDimitry Andric if (return_valobj_sp) {
1404ac9a064cSDimitry Andric if (llvm::Error error = return_valobj_sp->Dump(s)) {
1405ac9a064cSDimitry Andric s << "error: " << toString(std::move(error));
1406ac9a064cSDimitry Andric return false;
1407ac9a064cSDimitry Andric }
140812bd4897SEd Maste return true;
140912bd4897SEd Maste }
141012bd4897SEd Maste }
141112bd4897SEd Maste }
141212bd4897SEd Maste }
141312bd4897SEd Maste return false;
141412bd4897SEd Maste
141512bd4897SEd Maste case Entry::Type::ThreadCompletedExpression:
141614f1b3e8SDimitry Andric if (exe_ctx) {
141712bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
141814f1b3e8SDimitry Andric if (thread) {
141912bd4897SEd Maste StopInfoSP stop_info_sp = thread->GetStopInfo();
142014f1b3e8SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
142114f1b3e8SDimitry Andric ExpressionVariableSP expression_var_sp =
142214f1b3e8SDimitry Andric StopInfo::GetExpressionVariable(stop_info_sp);
142314f1b3e8SDimitry Andric if (expression_var_sp && expression_var_sp->GetValueObject()) {
1424ac9a064cSDimitry Andric if (llvm::Error error =
1425ac9a064cSDimitry Andric expression_var_sp->GetValueObject()->Dump(s)) {
1426ac9a064cSDimitry Andric s << "error: " << toString(std::move(error));
1427ac9a064cSDimitry Andric return false;
1428ac9a064cSDimitry Andric }
142912bd4897SEd Maste return true;
143012bd4897SEd Maste }
143112bd4897SEd Maste }
143212bd4897SEd Maste }
143312bd4897SEd Maste }
143412bd4897SEd Maste return false;
143512bd4897SEd Maste
143612bd4897SEd Maste case Entry::Type::ScriptThread:
143714f1b3e8SDimitry Andric if (exe_ctx) {
143812bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
143912bd4897SEd Maste if (thread)
144014f1b3e8SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
144114f1b3e8SDimitry Andric entry.string.c_str());
144212bd4897SEd Maste }
144312bd4897SEd Maste return false;
144412bd4897SEd Maste
144512bd4897SEd Maste case Entry::Type::ThreadInfo:
144614f1b3e8SDimitry Andric if (exe_ctx) {
144712bd4897SEd Maste Thread *thread = exe_ctx->GetThreadPtr();
144814f1b3e8SDimitry Andric if (thread) {
144912bd4897SEd Maste StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
145014f1b3e8SDimitry Andric if (object_sp &&
145161b440f5SDimitry Andric object_sp->GetType() == eStructuredDataTypeDictionary) {
145212bd4897SEd Maste if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
145312bd4897SEd Maste return true;
145412bd4897SEd Maste }
145512bd4897SEd Maste }
145612bd4897SEd Maste }
145712bd4897SEd Maste return false;
145812bd4897SEd Maste
145912bd4897SEd Maste case Entry::Type::TargetArch:
146014f1b3e8SDimitry Andric if (exe_ctx) {
146112bd4897SEd Maste Target *target = exe_ctx->GetTargetPtr();
146214f1b3e8SDimitry Andric if (target) {
146312bd4897SEd Maste const ArchSpec &arch = target->GetArchitecture();
146414f1b3e8SDimitry Andric if (arch.IsValid()) {
146512bd4897SEd Maste s.PutCString(arch.GetArchitectureName());
146612bd4897SEd Maste return true;
146712bd4897SEd Maste }
146812bd4897SEd Maste }
146912bd4897SEd Maste }
147012bd4897SEd Maste return false;
147112bd4897SEd Maste
147212bd4897SEd Maste case Entry::Type::ScriptTarget:
147314f1b3e8SDimitry Andric if (exe_ctx) {
147412bd4897SEd Maste Target *target = exe_ctx->GetTargetPtr();
147512bd4897SEd Maste if (target)
147614f1b3e8SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, target,
147714f1b3e8SDimitry Andric entry.string.c_str());
147812bd4897SEd Maste }
147912bd4897SEd Maste return false;
148012bd4897SEd Maste
148112bd4897SEd Maste case Entry::Type::ModuleFile:
148214f1b3e8SDimitry Andric if (sc) {
148312bd4897SEd Maste Module *module = sc->module_sp.get();
148414f1b3e8SDimitry Andric if (module) {
148512bd4897SEd Maste if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
148612bd4897SEd Maste return true;
148712bd4897SEd Maste }
148812bd4897SEd Maste }
148912bd4897SEd Maste return false;
149012bd4897SEd Maste
149112bd4897SEd Maste case Entry::Type::File:
149214f1b3e8SDimitry Andric if (sc) {
149312bd4897SEd Maste CompileUnit *cu = sc->comp_unit;
149414f1b3e8SDimitry Andric if (cu) {
1495706b4fc4SDimitry Andric if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
149612bd4897SEd Maste return true;
149712bd4897SEd Maste }
149812bd4897SEd Maste }
149912bd4897SEd Maste return false;
150012bd4897SEd Maste
15015e95aa85SEd Maste case Entry::Type::Lang:
150214f1b3e8SDimitry Andric if (sc) {
15035e95aa85SEd Maste CompileUnit *cu = sc->comp_unit;
150414f1b3e8SDimitry Andric if (cu) {
150514f1b3e8SDimitry Andric const char *lang_name =
150614f1b3e8SDimitry Andric Language::GetNameForLanguageType(cu->GetLanguage());
150714f1b3e8SDimitry Andric if (lang_name) {
15085e95aa85SEd Maste s.PutCString(lang_name);
15095e95aa85SEd Maste return true;
15105e95aa85SEd Maste }
15115e95aa85SEd Maste }
15125e95aa85SEd Maste }
15135e95aa85SEd Maste return false;
15145e95aa85SEd Maste
151512bd4897SEd Maste case Entry::Type::FrameIndex:
151614f1b3e8SDimitry Andric if (exe_ctx) {
151712bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
151814f1b3e8SDimitry Andric if (frame) {
151912bd4897SEd Maste const char *format = "%" PRIu32;
152012bd4897SEd Maste if (!entry.printf_format.empty())
152112bd4897SEd Maste format = entry.printf_format.c_str();
152212bd4897SEd Maste s.Printf(format, frame->GetFrameIndex());
152312bd4897SEd Maste return true;
152412bd4897SEd Maste }
152512bd4897SEd Maste }
152612bd4897SEd Maste return false;
152712bd4897SEd Maste
152812bd4897SEd Maste case Entry::Type::FrameRegisterPC:
152914f1b3e8SDimitry Andric if (exe_ctx) {
153012bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
153114f1b3e8SDimitry Andric if (frame) {
153212bd4897SEd Maste const Address &pc_addr = frame->GetFrameCodeAddress();
153314f1b3e8SDimitry Andric if (pc_addr.IsValid()) {
1534706b4fc4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
153512bd4897SEd Maste return true;
153612bd4897SEd Maste }
153712bd4897SEd Maste }
153812bd4897SEd Maste }
153912bd4897SEd Maste return false;
154012bd4897SEd Maste
154112bd4897SEd Maste case Entry::Type::FrameRegisterSP:
154214f1b3e8SDimitry Andric if (exe_ctx) {
154312bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
154414f1b3e8SDimitry Andric if (frame) {
154514f1b3e8SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
154614f1b3e8SDimitry Andric (lldb::Format)entry.number))
154712bd4897SEd Maste return true;
154812bd4897SEd Maste }
154912bd4897SEd Maste }
155012bd4897SEd Maste return false;
155112bd4897SEd Maste
155212bd4897SEd Maste case Entry::Type::FrameRegisterFP:
155314f1b3e8SDimitry Andric if (exe_ctx) {
155412bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
155514f1b3e8SDimitry Andric if (frame) {
155614f1b3e8SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
155714f1b3e8SDimitry Andric (lldb::Format)entry.number))
155812bd4897SEd Maste return true;
155912bd4897SEd Maste }
156012bd4897SEd Maste }
156112bd4897SEd Maste return false;
156212bd4897SEd Maste
156312bd4897SEd Maste case Entry::Type::FrameRegisterFlags:
156414f1b3e8SDimitry Andric if (exe_ctx) {
156512bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
156614f1b3e8SDimitry Andric if (frame) {
156714f1b3e8SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric,
156814f1b3e8SDimitry Andric LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
156912bd4897SEd Maste return true;
157012bd4897SEd Maste }
157112bd4897SEd Maste }
157212bd4897SEd Maste return false;
157312bd4897SEd Maste
157414f1b3e8SDimitry Andric case Entry::Type::FrameNoDebug:
157514f1b3e8SDimitry Andric if (exe_ctx) {
157612bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
157714f1b3e8SDimitry Andric if (frame) {
157814f1b3e8SDimitry Andric return !frame->HasDebugInformation();
157914f1b3e8SDimitry Andric }
158014f1b3e8SDimitry Andric }
158114f1b3e8SDimitry Andric return true;
158214f1b3e8SDimitry Andric
158314f1b3e8SDimitry Andric case Entry::Type::FrameRegisterByName:
158414f1b3e8SDimitry Andric if (exe_ctx) {
158514f1b3e8SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
158614f1b3e8SDimitry Andric if (frame) {
158714f1b3e8SDimitry Andric if (DumpRegister(s, frame, entry.string.c_str(),
158814f1b3e8SDimitry Andric (lldb::Format)entry.number))
158912bd4897SEd Maste return true;
159012bd4897SEd Maste }
159112bd4897SEd Maste }
159212bd4897SEd Maste return false;
159312bd4897SEd Maste
159494994d37SDimitry Andric case Entry::Type::FrameIsArtificial: {
159594994d37SDimitry Andric if (exe_ctx)
159694994d37SDimitry Andric if (StackFrame *frame = exe_ctx->GetFramePtr())
159794994d37SDimitry Andric return frame->IsArtificial();
159894994d37SDimitry Andric return false;
159994994d37SDimitry Andric }
160094994d37SDimitry Andric
160112bd4897SEd Maste case Entry::Type::ScriptFrame:
160214f1b3e8SDimitry Andric if (exe_ctx) {
160312bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
160412bd4897SEd Maste if (frame)
160514f1b3e8SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
160614f1b3e8SDimitry Andric entry.string.c_str());
160712bd4897SEd Maste }
160812bd4897SEd Maste return false;
160912bd4897SEd Maste
161012bd4897SEd Maste case Entry::Type::FunctionID:
161114f1b3e8SDimitry Andric if (sc) {
161214f1b3e8SDimitry Andric if (sc->function) {
161312bd4897SEd Maste s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
161412bd4897SEd Maste return true;
161514f1b3e8SDimitry Andric } else if (sc->symbol) {
161612bd4897SEd Maste s.Printf("symbol[%u]", sc->symbol->GetID());
161712bd4897SEd Maste return true;
161812bd4897SEd Maste }
161912bd4897SEd Maste }
162012bd4897SEd Maste return false;
162112bd4897SEd Maste
162212bd4897SEd Maste case Entry::Type::FunctionDidChange:
162312bd4897SEd Maste return function_changed;
162412bd4897SEd Maste
162512bd4897SEd Maste case Entry::Type::FunctionInitialFunction:
162612bd4897SEd Maste return initial_function;
162712bd4897SEd Maste
162814f1b3e8SDimitry Andric case Entry::Type::FunctionName: {
1629344a3780SDimitry Andric if (!sc)
1630344a3780SDimitry Andric return false;
1631344a3780SDimitry Andric
1632e81d9d49SDimitry Andric Language *language_plugin = nullptr;
1633e81d9d49SDimitry Andric bool language_plugin_handled = false;
1634e81d9d49SDimitry Andric StreamString ss;
1635344a3780SDimitry Andric
1636e81d9d49SDimitry Andric if (sc->function)
1637e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1638e81d9d49SDimitry Andric else if (sc->symbol)
1639e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1640344a3780SDimitry Andric
1641344a3780SDimitry Andric if (language_plugin)
164214f1b3e8SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
164314f1b3e8SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1644344a3780SDimitry Andric
164514f1b3e8SDimitry Andric if (language_plugin_handled) {
164614f1b3e8SDimitry Andric s << ss.GetString();
1647e81d9d49SDimitry Andric return true;
164814f1b3e8SDimitry Andric } else {
1649f3fbd1c0SDimitry Andric const char *name = nullptr;
165012bd4897SEd Maste if (sc->function)
1651f3fbd1c0SDimitry Andric name = sc->function->GetName().AsCString(nullptr);
165212bd4897SEd Maste else if (sc->symbol)
1653f3fbd1c0SDimitry Andric name = sc->symbol->GetName().AsCString(nullptr);
1654344a3780SDimitry Andric
165514f1b3e8SDimitry Andric if (name) {
165612bd4897SEd Maste s.PutCString(name);
16574df029ccSDimitry Andric FormatInlinedBlock(s, sc->block);
165812bd4897SEd Maste return true;
165912bd4897SEd Maste }
166012bd4897SEd Maste }
1661e81d9d49SDimitry Andric }
166212bd4897SEd Maste return false;
166312bd4897SEd Maste
166414f1b3e8SDimitry Andric case Entry::Type::FunctionNameNoArgs: {
1665344a3780SDimitry Andric if (!sc)
1666344a3780SDimitry Andric return false;
1667344a3780SDimitry Andric
1668e81d9d49SDimitry Andric Language *language_plugin = nullptr;
1669e81d9d49SDimitry Andric bool language_plugin_handled = false;
1670e81d9d49SDimitry Andric StreamString ss;
1671e81d9d49SDimitry Andric if (sc->function)
1672e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1673e81d9d49SDimitry Andric else if (sc->symbol)
1674e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1675344a3780SDimitry Andric
1676344a3780SDimitry Andric if (language_plugin)
167714f1b3e8SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
167814f1b3e8SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1679e81d9d49SDimitry Andric ss);
1680344a3780SDimitry Andric
168114f1b3e8SDimitry Andric if (language_plugin_handled) {
168214f1b3e8SDimitry Andric s << ss.GetString();
1683e81d9d49SDimitry Andric return true;
168414f1b3e8SDimitry Andric } else {
168512bd4897SEd Maste ConstString name;
168612bd4897SEd Maste if (sc->function)
1687027f1c96SDimitry Andric name = sc->function->GetNameNoArguments();
168812bd4897SEd Maste else if (sc->symbol)
1689027f1c96SDimitry Andric name = sc->symbol->GetNameNoArguments();
169014f1b3e8SDimitry Andric if (name) {
169112bd4897SEd Maste s.PutCString(name.GetCString());
16924df029ccSDimitry Andric FormatInlinedBlock(s, sc->block);
169312bd4897SEd Maste return true;
169412bd4897SEd Maste }
169512bd4897SEd Maste }
1696e81d9d49SDimitry Andric }
169712bd4897SEd Maste return false;
169812bd4897SEd Maste
169914f1b3e8SDimitry Andric case Entry::Type::FunctionNameWithArgs: {
1700344a3780SDimitry Andric if (!sc)
1701344a3780SDimitry Andric return false;
1702344a3780SDimitry Andric
1703e81d9d49SDimitry Andric Language *language_plugin = nullptr;
1704e81d9d49SDimitry Andric bool language_plugin_handled = false;
1705e81d9d49SDimitry Andric StreamString ss;
1706e81d9d49SDimitry Andric if (sc->function)
1707e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1708e81d9d49SDimitry Andric else if (sc->symbol)
1709e81d9d49SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1710344a3780SDimitry Andric
1711344a3780SDimitry Andric if (language_plugin)
171214f1b3e8SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
171314f1b3e8SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1714344a3780SDimitry Andric
171514f1b3e8SDimitry Andric if (language_plugin_handled) {
171614f1b3e8SDimitry Andric s << ss.GetString();
1717e81d9d49SDimitry Andric return true;
171814f1b3e8SDimitry Andric } else {
171912bd4897SEd Maste // Print the function name with arguments in it
172014f1b3e8SDimitry Andric if (sc->function) {
172114f1b3e8SDimitry Andric ExecutionContextScope *exe_scope =
172214f1b3e8SDimitry Andric exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1723f3fbd1c0SDimitry Andric const char *cstr = sc->function->GetName().AsCString(nullptr);
172414f1b3e8SDimitry Andric if (cstr) {
1725f3fbd1c0SDimitry Andric const InlineFunctionInfo *inline_info = nullptr;
172612bd4897SEd Maste VariableListSP variable_list_sp;
172712bd4897SEd Maste bool get_function_vars = true;
172814f1b3e8SDimitry Andric if (sc->block) {
172912bd4897SEd Maste Block *inline_block = sc->block->GetContainingInlinedBlock();
173012bd4897SEd Maste
173114f1b3e8SDimitry Andric if (inline_block) {
173212bd4897SEd Maste get_function_vars = false;
17334df029ccSDimitry Andric inline_info = inline_block->GetInlinedFunctionInfo();
173412bd4897SEd Maste if (inline_info)
173512bd4897SEd Maste variable_list_sp = inline_block->GetBlockVariableList(true);
173612bd4897SEd Maste }
173712bd4897SEd Maste }
173812bd4897SEd Maste
173914f1b3e8SDimitry Andric if (get_function_vars) {
174014f1b3e8SDimitry Andric variable_list_sp =
174114f1b3e8SDimitry Andric sc->function->GetBlock(true).GetBlockVariableList(true);
174212bd4897SEd Maste }
174312bd4897SEd Maste
174414f1b3e8SDimitry Andric if (inline_info) {
174512bd4897SEd Maste s.PutCString(cstr);
174612bd4897SEd Maste s.PutCString(" [inlined] ");
1747cfca06d7SDimitry Andric cstr = inline_info->GetName().GetCString();
174812bd4897SEd Maste }
174912bd4897SEd Maste
175012bd4897SEd Maste VariableList args;
175112bd4897SEd Maste if (variable_list_sp)
175214f1b3e8SDimitry Andric variable_list_sp->AppendVariablesWithScope(
175314f1b3e8SDimitry Andric eValueTypeVariableArgument, args);
175414f1b3e8SDimitry Andric if (args.GetSize() > 0) {
1755e3b55780SDimitry Andric PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
175614f1b3e8SDimitry Andric } else {
175712bd4897SEd Maste s.PutCString(cstr);
175812bd4897SEd Maste }
175912bd4897SEd Maste return true;
176012bd4897SEd Maste }
176114f1b3e8SDimitry Andric } else if (sc->symbol) {
1762f3fbd1c0SDimitry Andric const char *cstr = sc->symbol->GetName().AsCString(nullptr);
176314f1b3e8SDimitry Andric if (cstr) {
176412bd4897SEd Maste s.PutCString(cstr);
176512bd4897SEd Maste return true;
176612bd4897SEd Maste }
176712bd4897SEd Maste }
176812bd4897SEd Maste }
1769e81d9d49SDimitry Andric }
177012bd4897SEd Maste return false;
177112bd4897SEd Maste
1772706b4fc4SDimitry Andric case Entry::Type::FunctionMangledName: {
1773344a3780SDimitry Andric if (!sc)
1774344a3780SDimitry Andric return false;
1775344a3780SDimitry Andric
1776706b4fc4SDimitry Andric const char *name = nullptr;
1777706b4fc4SDimitry Andric if (sc->symbol)
1778cfca06d7SDimitry Andric name =
1779cfca06d7SDimitry Andric sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
1780706b4fc4SDimitry Andric else if (sc->function)
1781706b4fc4SDimitry Andric name = sc->function->GetMangled()
1782cfca06d7SDimitry Andric .GetName(Mangled::ePreferMangled)
1783706b4fc4SDimitry Andric .AsCString();
1784706b4fc4SDimitry Andric
1785706b4fc4SDimitry Andric if (!name)
1786706b4fc4SDimitry Andric return false;
1787706b4fc4SDimitry Andric s.PutCString(name);
17884df029ccSDimitry Andric FormatInlinedBlock(s, sc->block);
1789706b4fc4SDimitry Andric return true;
1790706b4fc4SDimitry Andric }
179112bd4897SEd Maste case Entry::Type::FunctionAddrOffset:
179214f1b3e8SDimitry Andric if (addr) {
179314f1b3e8SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
179414f1b3e8SDimitry Andric false))
179512bd4897SEd Maste return true;
179612bd4897SEd Maste }
179712bd4897SEd Maste return false;
179812bd4897SEd Maste
179912bd4897SEd Maste case Entry::Type::FunctionAddrOffsetConcrete:
180014f1b3e8SDimitry Andric if (addr) {
180114f1b3e8SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
180214f1b3e8SDimitry Andric true))
180312bd4897SEd Maste return true;
180412bd4897SEd Maste }
180512bd4897SEd Maste return false;
180612bd4897SEd Maste
180712bd4897SEd Maste case Entry::Type::FunctionLineOffset:
1808344a3780SDimitry Andric if (sc)
1809344a3780SDimitry Andric return (DumpAddressOffsetFromFunction(
1810344a3780SDimitry Andric s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
1811344a3780SDimitry Andric false));
1812344a3780SDimitry Andric return false;
181312bd4897SEd Maste
181412bd4897SEd Maste case Entry::Type::FunctionPCOffset:
181514f1b3e8SDimitry Andric if (exe_ctx) {
181612bd4897SEd Maste StackFrame *frame = exe_ctx->GetFramePtr();
181714f1b3e8SDimitry Andric if (frame) {
181814f1b3e8SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
181914f1b3e8SDimitry Andric frame->GetFrameCodeAddress(), false,
182014f1b3e8SDimitry Andric false, false))
182112bd4897SEd Maste return true;
182212bd4897SEd Maste }
182312bd4897SEd Maste }
182412bd4897SEd Maste return false;
182512bd4897SEd Maste
18265e95aa85SEd Maste case Entry::Type::FunctionChanged:
1827f3fbd1c0SDimitry Andric return function_changed;
18285e95aa85SEd Maste
182914f1b3e8SDimitry Andric case Entry::Type::FunctionIsOptimized: {
1830e81d9d49SDimitry Andric bool is_optimized = false;
1831344a3780SDimitry Andric if (sc && sc->function && sc->function->GetIsOptimized()) {
1832e81d9d49SDimitry Andric is_optimized = true;
1833e81d9d49SDimitry Andric }
1834e81d9d49SDimitry Andric return is_optimized;
1835e81d9d49SDimitry Andric }
1836e81d9d49SDimitry Andric
18375e95aa85SEd Maste case Entry::Type::FunctionInitial:
1838f3fbd1c0SDimitry Andric return initial_function;
18395e95aa85SEd Maste
184012bd4897SEd Maste case Entry::Type::LineEntryFile:
184114f1b3e8SDimitry Andric if (sc && sc->line_entry.IsValid()) {
184212bd4897SEd Maste Module *module = sc->module_sp.get();
184314f1b3e8SDimitry Andric if (module) {
1844ac9a064cSDimitry Andric if (DumpFile(s, sc->line_entry.GetFile(), (FileKind)entry.number))
184512bd4897SEd Maste return true;
184612bd4897SEd Maste }
184712bd4897SEd Maste }
184812bd4897SEd Maste return false;
184912bd4897SEd Maste
185012bd4897SEd Maste case Entry::Type::LineEntryLineNumber:
185114f1b3e8SDimitry Andric if (sc && sc->line_entry.IsValid()) {
185212bd4897SEd Maste const char *format = "%" PRIu32;
185312bd4897SEd Maste if (!entry.printf_format.empty())
185412bd4897SEd Maste format = entry.printf_format.c_str();
185512bd4897SEd Maste s.Printf(format, sc->line_entry.line);
185612bd4897SEd Maste return true;
185712bd4897SEd Maste }
185812bd4897SEd Maste return false;
185912bd4897SEd Maste
186094994d37SDimitry Andric case Entry::Type::LineEntryColumn:
186194994d37SDimitry Andric if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
186294994d37SDimitry Andric const char *format = "%" PRIu32;
186394994d37SDimitry Andric if (!entry.printf_format.empty())
186494994d37SDimitry Andric format = entry.printf_format.c_str();
186594994d37SDimitry Andric s.Printf(format, sc->line_entry.column);
186694994d37SDimitry Andric return true;
186794994d37SDimitry Andric }
186894994d37SDimitry Andric return false;
186994994d37SDimitry Andric
187012bd4897SEd Maste case Entry::Type::LineEntryStartAddress:
187112bd4897SEd Maste case Entry::Type::LineEntryEndAddress:
187214f1b3e8SDimitry Andric if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
187312bd4897SEd Maste Address addr = sc->line_entry.range.GetBaseAddress();
187412bd4897SEd Maste
187512bd4897SEd Maste if (entry.type == Entry::Type::LineEntryEndAddress)
187612bd4897SEd Maste addr.Slide(sc->line_entry.range.GetByteSize());
1877706b4fc4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
187812bd4897SEd Maste return true;
187912bd4897SEd Maste }
188012bd4897SEd Maste return false;
188112bd4897SEd Maste
188212bd4897SEd Maste case Entry::Type::CurrentPCArrow:
188314f1b3e8SDimitry Andric if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
188414f1b3e8SDimitry Andric RegisterContextSP reg_ctx =
188514f1b3e8SDimitry Andric exe_ctx->GetFramePtr()->GetRegisterContextSP();
188614f1b3e8SDimitry Andric if (reg_ctx) {
188712bd4897SEd Maste addr_t pc_loadaddr = reg_ctx->GetPC();
188814f1b3e8SDimitry Andric if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
188912bd4897SEd Maste Address pc;
189012bd4897SEd Maste pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
189114f1b3e8SDimitry Andric if (pc == *addr) {
189212bd4897SEd Maste s.Printf("-> ");
189312bd4897SEd Maste return true;
189412bd4897SEd Maste }
189512bd4897SEd Maste }
189612bd4897SEd Maste }
189712bd4897SEd Maste s.Printf(" ");
189812bd4897SEd Maste return true;
189912bd4897SEd Maste }
190012bd4897SEd Maste return false;
190112bd4897SEd Maste }
190212bd4897SEd Maste return false;
190312bd4897SEd Maste }
190412bd4897SEd Maste
DumpCommaSeparatedChildEntryNames(Stream & s,const Definition * parent)1905344a3780SDimitry Andric static bool DumpCommaSeparatedChildEntryNames(Stream &s,
1906344a3780SDimitry Andric const Definition *parent) {
190714f1b3e8SDimitry Andric if (parent->children) {
190812bd4897SEd Maste const size_t n = parent->num_children;
190914f1b3e8SDimitry Andric for (size_t i = 0; i < n; ++i) {
191012bd4897SEd Maste if (i > 0)
191112bd4897SEd Maste s.PutCString(", ");
191212bd4897SEd Maste s.Printf("\"%s\"", parent->children[i].name);
191312bd4897SEd Maste }
191412bd4897SEd Maste return true;
191512bd4897SEd Maste }
191612bd4897SEd Maste return false;
191712bd4897SEd Maste }
191812bd4897SEd Maste
ParseEntry(const llvm::StringRef & format_str,const Definition * parent,FormatEntity::Entry & entry)1919b76161e4SDimitry Andric static Status ParseEntry(const llvm::StringRef &format_str,
1920344a3780SDimitry Andric const Definition *parent, FormatEntity::Entry &entry) {
1921b76161e4SDimitry Andric Status error;
192212bd4897SEd Maste
192312bd4897SEd Maste const size_t sep_pos = format_str.find_first_of(".[:");
192414f1b3e8SDimitry Andric const char sep_char =
192514f1b3e8SDimitry Andric (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
192612bd4897SEd Maste llvm::StringRef key = format_str.substr(0, sep_pos);
192712bd4897SEd Maste
192812bd4897SEd Maste const size_t n = parent->num_children;
192914f1b3e8SDimitry Andric for (size_t i = 0; i < n; ++i) {
1930344a3780SDimitry Andric const Definition *entry_def = parent->children + i;
1931ac9a064cSDimitry Andric if (key == entry_def->name || entry_def->name[0] == '*') {
193212bd4897SEd Maste llvm::StringRef value;
193312bd4897SEd Maste if (sep_char)
193414f1b3e8SDimitry Andric value =
193514f1b3e8SDimitry Andric format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
193614f1b3e8SDimitry Andric switch (entry_def->type) {
193712bd4897SEd Maste case FormatEntity::Entry::Type::ParentString:
1938e81d9d49SDimitry Andric entry.string = format_str.str();
193912bd4897SEd Maste return error; // Success
194012bd4897SEd Maste
194112bd4897SEd Maste case FormatEntity::Entry::Type::ParentNumber:
194212bd4897SEd Maste entry.number = entry_def->data;
194312bd4897SEd Maste return error; // Success
194412bd4897SEd Maste
19455f29bb8aSDimitry Andric case FormatEntity::Entry::Type::EscapeCode:
194612bd4897SEd Maste entry.type = entry_def->type;
194712bd4897SEd Maste entry.string = entry_def->string;
194812bd4897SEd Maste return error; // Success
194912bd4897SEd Maste
195012bd4897SEd Maste default:
195112bd4897SEd Maste entry.type = entry_def->type;
195212bd4897SEd Maste break;
195312bd4897SEd Maste }
195412bd4897SEd Maste
195514f1b3e8SDimitry Andric if (value.empty()) {
195614f1b3e8SDimitry Andric if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
195714f1b3e8SDimitry Andric if (entry_def->children) {
195812bd4897SEd Maste StreamString error_strm;
195914f1b3e8SDimitry Andric error_strm.Printf("'%s' can't be specified on its own, you must "
196014f1b3e8SDimitry Andric "access one of its children: ",
196114f1b3e8SDimitry Andric entry_def->name);
196212bd4897SEd Maste DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
196314f1b3e8SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
196414f1b3e8SDimitry Andric } else if (sep_char == ':') {
196514f1b3e8SDimitry Andric // Any value whose separator is a with a ':' means this value has a
1966f73363f1SDimitry Andric // string argument that needs to be stored in the entry (like
1967f73363f1SDimitry Andric // "${script.var:}"). In this case the string value is the empty
1968f73363f1SDimitry Andric // string which is ok.
196914f1b3e8SDimitry Andric } else {
197012bd4897SEd Maste error.SetErrorStringWithFormat("%s", "invalid entry definitions");
197112bd4897SEd Maste }
197212bd4897SEd Maste }
197314f1b3e8SDimitry Andric } else {
197414f1b3e8SDimitry Andric if (entry_def->children) {
197512bd4897SEd Maste error = ParseEntry(value, entry_def, entry);
197614f1b3e8SDimitry Andric } else if (sep_char == ':') {
197714f1b3e8SDimitry Andric // Any value whose separator is a with a ':' means this value has a
1978f73363f1SDimitry Andric // string argument that needs to be stored in the entry (like
197914f1b3e8SDimitry Andric // "${script.var:modulename.function}")
1980e81d9d49SDimitry Andric entry.string = value.str();
198114f1b3e8SDimitry Andric } else {
198214f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
198314f1b3e8SDimitry Andric "'%s' followed by '%s' but it has no children", key.str().c_str(),
198412bd4897SEd Maste value.str().c_str());
198512bd4897SEd Maste }
198612bd4897SEd Maste }
198712bd4897SEd Maste return error;
198812bd4897SEd Maste }
198912bd4897SEd Maste }
199012bd4897SEd Maste StreamString error_strm;
199112bd4897SEd Maste if (parent->type == FormatEntity::Entry::Type::Root)
199214f1b3e8SDimitry Andric error_strm.Printf(
199314f1b3e8SDimitry Andric "invalid top level item '%s'. Valid top level items are: ",
199414f1b3e8SDimitry Andric key.str().c_str());
199512bd4897SEd Maste else
199614f1b3e8SDimitry Andric error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
199714f1b3e8SDimitry Andric key.str().c_str(), parent->name);
199812bd4897SEd Maste DumpCommaSeparatedChildEntryNames(error_strm, parent);
199914f1b3e8SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
200012bd4897SEd Maste return error;
200112bd4897SEd Maste }
200212bd4897SEd Maste
FindEntry(const llvm::StringRef & format_str,const Definition * parent,llvm::StringRef & remainder)2003344a3780SDimitry Andric static const Definition *FindEntry(const llvm::StringRef &format_str,
2004344a3780SDimitry Andric const Definition *parent,
200514f1b3e8SDimitry Andric llvm::StringRef &remainder) {
2006b76161e4SDimitry Andric Status error;
200712bd4897SEd Maste
200812bd4897SEd Maste std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
200912bd4897SEd Maste const size_t n = parent->num_children;
201014f1b3e8SDimitry Andric for (size_t i = 0; i < n; ++i) {
2011344a3780SDimitry Andric const Definition *entry_def = parent->children + i;
2012ac9a064cSDimitry Andric if (p.first == entry_def->name || entry_def->name[0] == '*') {
201314f1b3e8SDimitry Andric if (p.second.empty()) {
201412bd4897SEd Maste if (format_str.back() == '.')
201512bd4897SEd Maste remainder = format_str.drop_front(format_str.size() - 1);
201612bd4897SEd Maste else
201712bd4897SEd Maste remainder = llvm::StringRef(); // Exact match
201812bd4897SEd Maste return entry_def;
201914f1b3e8SDimitry Andric } else {
202014f1b3e8SDimitry Andric if (entry_def->children) {
202112bd4897SEd Maste return FindEntry(p.second, entry_def, remainder);
202214f1b3e8SDimitry Andric } else {
202312bd4897SEd Maste remainder = p.second;
202412bd4897SEd Maste return entry_def;
202512bd4897SEd Maste }
202612bd4897SEd Maste }
202712bd4897SEd Maste }
202812bd4897SEd Maste }
202912bd4897SEd Maste remainder = format_str;
203012bd4897SEd Maste return parent;
203112bd4897SEd Maste }
203212bd4897SEd Maste
ParseInternal(llvm::StringRef & format,Entry & parent_entry,uint32_t depth)2033b1c73532SDimitry Andric static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
203414f1b3e8SDimitry Andric uint32_t depth) {
2035b76161e4SDimitry Andric Status error;
203614f1b3e8SDimitry Andric while (!format.empty() && error.Success()) {
203712bd4897SEd Maste const size_t non_special_chars = format.find_first_of("${}\\");
203812bd4897SEd Maste
203914f1b3e8SDimitry Andric if (non_special_chars == llvm::StringRef::npos) {
204012bd4897SEd Maste // No special characters, just string bytes so add them and we are done
204112bd4897SEd Maste parent_entry.AppendText(format);
204212bd4897SEd Maste return error;
204312bd4897SEd Maste }
204412bd4897SEd Maste
204514f1b3e8SDimitry Andric if (non_special_chars > 0) {
204614f1b3e8SDimitry Andric // We have a special character, so add all characters before these as a
204714f1b3e8SDimitry Andric // plain string
204812bd4897SEd Maste parent_entry.AppendText(format.substr(0, non_special_chars));
204912bd4897SEd Maste format = format.drop_front(non_special_chars);
205012bd4897SEd Maste }
205112bd4897SEd Maste
205214f1b3e8SDimitry Andric switch (format[0]) {
205312bd4897SEd Maste case '\0':
205412bd4897SEd Maste return error;
205512bd4897SEd Maste
205614f1b3e8SDimitry Andric case '{': {
205712bd4897SEd Maste format = format.drop_front(); // Skip the '{'
205812bd4897SEd Maste Entry scope_entry(Entry::Type::Scope);
2059b1c73532SDimitry Andric error = ParseInternal(format, scope_entry, depth + 1);
206012bd4897SEd Maste if (error.Fail())
206112bd4897SEd Maste return error;
206212bd4897SEd Maste parent_entry.AppendEntry(std::move(scope_entry));
206314f1b3e8SDimitry Andric } break;
206412bd4897SEd Maste
206512bd4897SEd Maste case '}':
206612bd4897SEd Maste if (depth == 0)
206712bd4897SEd Maste error.SetErrorString("unmatched '}' character");
206812bd4897SEd Maste else
206914f1b3e8SDimitry Andric format =
207014f1b3e8SDimitry Andric format
207114f1b3e8SDimitry Andric .drop_front(); // Skip the '}' as we are at the end of the scope
207212bd4897SEd Maste return error;
207312bd4897SEd Maste
207414f1b3e8SDimitry Andric case '\\': {
207512bd4897SEd Maste format = format.drop_front(); // Skip the '\' character
207614f1b3e8SDimitry Andric if (format.empty()) {
207714f1b3e8SDimitry Andric error.SetErrorString(
207814f1b3e8SDimitry Andric "'\\' character was not followed by another character");
207912bd4897SEd Maste return error;
208012bd4897SEd Maste }
208112bd4897SEd Maste
208212bd4897SEd Maste const char desens_char = format[0];
208312bd4897SEd Maste format = format.drop_front(); // Skip the desensitized char character
208414f1b3e8SDimitry Andric switch (desens_char) {
208514f1b3e8SDimitry Andric case 'a':
208614f1b3e8SDimitry Andric parent_entry.AppendChar('\a');
208714f1b3e8SDimitry Andric break;
208814f1b3e8SDimitry Andric case 'b':
208914f1b3e8SDimitry Andric parent_entry.AppendChar('\b');
209014f1b3e8SDimitry Andric break;
209114f1b3e8SDimitry Andric case 'f':
209214f1b3e8SDimitry Andric parent_entry.AppendChar('\f');
209314f1b3e8SDimitry Andric break;
209414f1b3e8SDimitry Andric case 'n':
209514f1b3e8SDimitry Andric parent_entry.AppendChar('\n');
209614f1b3e8SDimitry Andric break;
209714f1b3e8SDimitry Andric case 'r':
209814f1b3e8SDimitry Andric parent_entry.AppendChar('\r');
209914f1b3e8SDimitry Andric break;
210014f1b3e8SDimitry Andric case 't':
210114f1b3e8SDimitry Andric parent_entry.AppendChar('\t');
210214f1b3e8SDimitry Andric break;
210314f1b3e8SDimitry Andric case 'v':
210414f1b3e8SDimitry Andric parent_entry.AppendChar('\v');
210514f1b3e8SDimitry Andric break;
210614f1b3e8SDimitry Andric case '\'':
210714f1b3e8SDimitry Andric parent_entry.AppendChar('\'');
210814f1b3e8SDimitry Andric break;
210914f1b3e8SDimitry Andric case '\\':
211014f1b3e8SDimitry Andric parent_entry.AppendChar('\\');
211114f1b3e8SDimitry Andric break;
211212bd4897SEd Maste case '0':
211312bd4897SEd Maste // 1 to 3 octal chars
211412bd4897SEd Maste {
2115f73363f1SDimitry Andric // Make a string that can hold onto the initial zero char, up to 3
2116f73363f1SDimitry Andric // octal digits, and a terminating NULL.
211712bd4897SEd Maste char oct_str[5] = {0, 0, 0, 0, 0};
211812bd4897SEd Maste
211912bd4897SEd Maste int i;
212012bd4897SEd Maste for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
212112bd4897SEd Maste oct_str[i] = format[i];
212212bd4897SEd Maste
2123f73363f1SDimitry Andric // We don't want to consume the last octal character since the main
2124f73363f1SDimitry Andric // for loop will do this for us, so we advance p by one less than i
2125f73363f1SDimitry Andric // (even if i is zero)
212612bd4897SEd Maste format = format.drop_front(i);
2127f3fbd1c0SDimitry Andric unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
212814f1b3e8SDimitry Andric if (octal_value <= UINT8_MAX) {
212912bd4897SEd Maste parent_entry.AppendChar((char)octal_value);
213014f1b3e8SDimitry Andric } else {
213112bd4897SEd Maste error.SetErrorString("octal number is larger than a single byte");
213212bd4897SEd Maste return error;
213312bd4897SEd Maste }
213412bd4897SEd Maste }
213512bd4897SEd Maste break;
213612bd4897SEd Maste
213712bd4897SEd Maste case 'x':
213812bd4897SEd Maste // hex number in the format
213914f1b3e8SDimitry Andric if (isxdigit(format[0])) {
214012bd4897SEd Maste // Make a string that can hold onto two hex chars plus a
214112bd4897SEd Maste // NULL terminator
214212bd4897SEd Maste char hex_str[3] = {0, 0, 0};
214312bd4897SEd Maste hex_str[0] = format[0];
214412bd4897SEd Maste
214512bd4897SEd Maste format = format.drop_front();
214612bd4897SEd Maste
214714f1b3e8SDimitry Andric if (isxdigit(format[0])) {
214812bd4897SEd Maste hex_str[1] = format[0];
214912bd4897SEd Maste format = format.drop_front();
215012bd4897SEd Maste }
215112bd4897SEd Maste
2152f3fbd1c0SDimitry Andric unsigned long hex_value = strtoul(hex_str, nullptr, 16);
215314f1b3e8SDimitry Andric if (hex_value <= UINT8_MAX) {
215412bd4897SEd Maste parent_entry.AppendChar((char)hex_value);
215514f1b3e8SDimitry Andric } else {
215612bd4897SEd Maste error.SetErrorString("hex number is larger than a single byte");
215712bd4897SEd Maste return error;
215812bd4897SEd Maste }
215914f1b3e8SDimitry Andric } else {
216012bd4897SEd Maste parent_entry.AppendChar(desens_char);
216112bd4897SEd Maste }
216212bd4897SEd Maste break;
216312bd4897SEd Maste
216412bd4897SEd Maste default:
2165f73363f1SDimitry Andric // Just desensitize any other character by just printing what came
2166f73363f1SDimitry Andric // after the '\'
216712bd4897SEd Maste parent_entry.AppendChar(desens_char);
216812bd4897SEd Maste break;
216912bd4897SEd Maste }
217014f1b3e8SDimitry Andric } break;
217112bd4897SEd Maste
217212bd4897SEd Maste case '$':
2173ac9a064cSDimitry Andric format = format.drop_front(); // Skip the '$'
2174ac9a064cSDimitry Andric if (format.empty() || format.front() != '{') {
2175ac9a064cSDimitry Andric // Print '$' when not followed by '{'.
217612bd4897SEd Maste parent_entry.AppendText("$");
217714f1b3e8SDimitry Andric } else {
217812bd4897SEd Maste format = format.drop_front(); // Skip the '{'
217912bd4897SEd Maste
218012bd4897SEd Maste llvm::StringRef variable, variable_format;
218114f1b3e8SDimitry Andric error = FormatEntity::ExtractVariableInfo(format, variable,
218214f1b3e8SDimitry Andric variable_format);
218312bd4897SEd Maste if (error.Fail())
218412bd4897SEd Maste return error;
218512bd4897SEd Maste bool verify_is_thread_id = false;
218612bd4897SEd Maste Entry entry;
218714f1b3e8SDimitry Andric if (!variable_format.empty()) {
2188e81d9d49SDimitry Andric entry.printf_format = variable_format.str();
218912bd4897SEd Maste
2190f73363f1SDimitry Andric // If the format contains a '%' we are going to assume this is a
2191f73363f1SDimitry Andric // printf style format. So if you want to format your thread ID
2192f73363f1SDimitry Andric // using "0x%llx" you can use: ${thread.id%0x%llx}
219312bd4897SEd Maste //
219412bd4897SEd Maste // If there is no '%' in the format, then it is assumed to be a
219512bd4897SEd Maste // LLDB format name, or one of the extended formats specified in
219612bd4897SEd Maste // the switch statement below.
219712bd4897SEd Maste
219814f1b3e8SDimitry Andric if (entry.printf_format.find('%') == std::string::npos) {
219912bd4897SEd Maste bool clear_printf = false;
220012bd4897SEd Maste
2201ac9a064cSDimitry Andric if (entry.printf_format.size() == 1) {
220214f1b3e8SDimitry Andric switch (entry.printf_format[0]) {
220312bd4897SEd Maste case '@': // if this is an @ sign, print ObjC description
220414f1b3e8SDimitry Andric entry.number = ValueObject::
220514f1b3e8SDimitry Andric eValueObjectRepresentationStyleLanguageSpecific;
220612bd4897SEd Maste clear_printf = true;
220712bd4897SEd Maste break;
220814f1b3e8SDimitry Andric case 'V': // if this is a V, print the value using the default
220914f1b3e8SDimitry Andric // format
221014f1b3e8SDimitry Andric entry.number =
221114f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue;
221212bd4897SEd Maste clear_printf = true;
221312bd4897SEd Maste break;
221412bd4897SEd Maste case 'L': // if this is an L, print the location of the value
221514f1b3e8SDimitry Andric entry.number =
221614f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleLocation;
221712bd4897SEd Maste clear_printf = true;
221812bd4897SEd Maste break;
221912bd4897SEd Maste case 'S': // if this is an S, print the summary after all
222014f1b3e8SDimitry Andric entry.number =
222114f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
222212bd4897SEd Maste clear_printf = true;
222312bd4897SEd Maste break;
222412bd4897SEd Maste case '#': // if this is a '#', print the number of children
222514f1b3e8SDimitry Andric entry.number =
222614f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleChildrenCount;
222712bd4897SEd Maste clear_printf = true;
222812bd4897SEd Maste break;
222912bd4897SEd Maste case 'T': // if this is a 'T', print the type
2230ac9a064cSDimitry Andric entry.number = ValueObject::eValueObjectRepresentationStyleType;
223112bd4897SEd Maste clear_printf = true;
223212bd4897SEd Maste break;
223312bd4897SEd Maste case 'N': // if this is a 'N', print the name
2234ac9a064cSDimitry Andric entry.number = ValueObject::eValueObjectRepresentationStyleName;
223512bd4897SEd Maste clear_printf = true;
223612bd4897SEd Maste break;
223712bd4897SEd Maste case '>': // if this is a '>', print the expression path
2238ac9a064cSDimitry Andric entry.number =
2239ac9a064cSDimitry Andric ValueObject::eValueObjectRepresentationStyleExpressionPath;
224012bd4897SEd Maste clear_printf = true;
224112bd4897SEd Maste break;
224212bd4897SEd Maste }
2243ac9a064cSDimitry Andric }
2244ac9a064cSDimitry Andric
2245ac9a064cSDimitry Andric if (entry.number == 0) {
2246ac9a064cSDimitry Andric if (FormatManager::GetFormatFromCString(
2247ac9a064cSDimitry Andric entry.printf_format.c_str(), entry.fmt)) {
224812bd4897SEd Maste clear_printf = true;
224914f1b3e8SDimitry Andric } else if (entry.printf_format == "tid") {
225012bd4897SEd Maste verify_is_thread_id = true;
225114f1b3e8SDimitry Andric } else {
225214f1b3e8SDimitry Andric error.SetErrorStringWithFormat("invalid format: '%s'",
225314f1b3e8SDimitry Andric entry.printf_format.c_str());
225412bd4897SEd Maste return error;
225512bd4897SEd Maste }
2256ac9a064cSDimitry Andric }
225712bd4897SEd Maste
225812bd4897SEd Maste // Our format string turned out to not be a printf style format
225912bd4897SEd Maste // so lets clear the string
226012bd4897SEd Maste if (clear_printf)
226112bd4897SEd Maste entry.printf_format.clear();
226212bd4897SEd Maste }
226312bd4897SEd Maste }
226412bd4897SEd Maste
226512bd4897SEd Maste // Check for dereferences
226614f1b3e8SDimitry Andric if (variable[0] == '*') {
226712bd4897SEd Maste entry.deref = true;
226812bd4897SEd Maste variable = variable.drop_front();
226912bd4897SEd Maste }
227012bd4897SEd Maste
227112bd4897SEd Maste error = ParseEntry(variable, &g_root, entry);
227212bd4897SEd Maste if (error.Fail())
227312bd4897SEd Maste return error;
227412bd4897SEd Maste
2275ac9a064cSDimitry Andric llvm::StringRef entry_string(entry.string);
2276ac9a064cSDimitry Andric if (entry_string.contains(':')) {
2277ac9a064cSDimitry Andric auto [_, llvm_format] = entry_string.split(':');
2278ac9a064cSDimitry Andric if (!llvm_format.empty() && !LLVMFormatPattern.match(llvm_format)) {
2279ac9a064cSDimitry Andric error.SetErrorStringWithFormat("invalid llvm format: '%s'",
2280ac9a064cSDimitry Andric llvm_format.data());
2281ac9a064cSDimitry Andric return error;
2282ac9a064cSDimitry Andric }
2283ac9a064cSDimitry Andric }
2284ac9a064cSDimitry Andric
228514f1b3e8SDimitry Andric if (verify_is_thread_id) {
228612bd4897SEd Maste if (entry.type != Entry::Type::ThreadID &&
228714f1b3e8SDimitry Andric entry.type != Entry::Type::ThreadProtocolID) {
228814f1b3e8SDimitry Andric error.SetErrorString("the 'tid' format can only be used on "
228914f1b3e8SDimitry Andric "${thread.id} and ${thread.protocol_id}");
229012bd4897SEd Maste }
229112bd4897SEd Maste }
229212bd4897SEd Maste
229314f1b3e8SDimitry Andric switch (entry.type) {
229412bd4897SEd Maste case Entry::Type::Variable:
229512bd4897SEd Maste case Entry::Type::VariableSynthetic:
229614f1b3e8SDimitry Andric if (entry.number == 0) {
229712bd4897SEd Maste if (entry.string.empty())
2298ac9a064cSDimitry Andric entry.number = ValueObject::eValueObjectRepresentationStyleValue;
229912bd4897SEd Maste else
230014f1b3e8SDimitry Andric entry.number =
230114f1b3e8SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
230212bd4897SEd Maste }
230312bd4897SEd Maste break;
230412bd4897SEd Maste default:
230514f1b3e8SDimitry Andric // Make sure someone didn't try to dereference anything but ${var}
230614f1b3e8SDimitry Andric // or ${svar}
230714f1b3e8SDimitry Andric if (entry.deref) {
230814f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
230914f1b3e8SDimitry Andric "${%s} can't be dereferenced, only ${var} and ${svar} can.",
231014f1b3e8SDimitry Andric variable.str().c_str());
231112bd4897SEd Maste return error;
231212bd4897SEd Maste }
231312bd4897SEd Maste }
231412bd4897SEd Maste parent_entry.AppendEntry(std::move(entry));
231512bd4897SEd Maste }
231612bd4897SEd Maste break;
231712bd4897SEd Maste }
231812bd4897SEd Maste }
231912bd4897SEd Maste return error;
232012bd4897SEd Maste }
232112bd4897SEd Maste
ExtractVariableInfo(llvm::StringRef & format_str,llvm::StringRef & variable_name,llvm::StringRef & variable_format)2322b76161e4SDimitry Andric Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
232314f1b3e8SDimitry Andric llvm::StringRef &variable_name,
232414f1b3e8SDimitry Andric llvm::StringRef &variable_format) {
2325b76161e4SDimitry Andric Status error;
232612bd4897SEd Maste variable_name = llvm::StringRef();
232712bd4897SEd Maste variable_format = llvm::StringRef();
232812bd4897SEd Maste
2329e81d9d49SDimitry Andric const size_t paren_pos = format_str.find('}');
233014f1b3e8SDimitry Andric if (paren_pos != llvm::StringRef::npos) {
2331e81d9d49SDimitry Andric const size_t percent_pos = format_str.find('%');
233214f1b3e8SDimitry Andric if (percent_pos < paren_pos) {
233314f1b3e8SDimitry Andric if (percent_pos > 0) {
233412bd4897SEd Maste if (percent_pos > 1)
233512bd4897SEd Maste variable_name = format_str.substr(0, percent_pos);
233614f1b3e8SDimitry Andric variable_format =
233714f1b3e8SDimitry Andric format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
233812bd4897SEd Maste }
233914f1b3e8SDimitry Andric } else {
234012bd4897SEd Maste variable_name = format_str.substr(0, paren_pos);
234112bd4897SEd Maste }
234212bd4897SEd Maste // Strip off elements and the formatting and the trailing '}'
234312bd4897SEd Maste format_str = format_str.substr(paren_pos + 1);
234414f1b3e8SDimitry Andric } else {
234514f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
234614f1b3e8SDimitry Andric "missing terminating '}' character for '${%s'",
234714f1b3e8SDimitry Andric format_str.str().c_str());
234812bd4897SEd Maste }
234912bd4897SEd Maste return error;
235012bd4897SEd Maste }
235112bd4897SEd Maste
FormatFileSpec(const FileSpec & file_spec,Stream & s,llvm::StringRef variable_name,llvm::StringRef variable_format)235214f1b3e8SDimitry Andric bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
235314f1b3e8SDimitry Andric llvm::StringRef variable_name,
235414f1b3e8SDimitry Andric llvm::StringRef variable_format) {
2355ac9a064cSDimitry Andric if (variable_name.empty() || variable_name == ".fullpath") {
2356706b4fc4SDimitry Andric file_spec.Dump(s.AsRawOstream());
235712bd4897SEd Maste return true;
2358ac9a064cSDimitry Andric } else if (variable_name == ".basename") {
2359cfca06d7SDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
236012bd4897SEd Maste return true;
2361ac9a064cSDimitry Andric } else if (variable_name == ".dirname") {
2362cfca06d7SDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
236312bd4897SEd Maste return true;
236412bd4897SEd Maste }
236512bd4897SEd Maste return false;
236612bd4897SEd Maste }
236712bd4897SEd Maste
MakeMatch(const llvm::StringRef & prefix,const char * suffix)236814f1b3e8SDimitry Andric static std::string MakeMatch(const llvm::StringRef &prefix,
236914f1b3e8SDimitry Andric const char *suffix) {
237012bd4897SEd Maste std::string match(prefix.str());
237112bd4897SEd Maste match.append(suffix);
2372e81d9d49SDimitry Andric return match;
237312bd4897SEd Maste }
237412bd4897SEd Maste
AddMatches(const Definition * def,const llvm::StringRef & prefix,const llvm::StringRef & match_prefix,StringList & matches)2375344a3780SDimitry Andric static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
237612bd4897SEd Maste const llvm::StringRef &match_prefix,
237714f1b3e8SDimitry Andric StringList &matches) {
237812bd4897SEd Maste const size_t n = def->num_children;
237914f1b3e8SDimitry Andric if (n > 0) {
238014f1b3e8SDimitry Andric for (size_t i = 0; i < n; ++i) {
2381e81d9d49SDimitry Andric std::string match = prefix.str();
238212bd4897SEd Maste if (match_prefix.empty())
238312bd4897SEd Maste matches.AppendString(MakeMatch(prefix, def->children[i].name));
238414f1b3e8SDimitry Andric else if (strncmp(def->children[i].name, match_prefix.data(),
238514f1b3e8SDimitry Andric match_prefix.size()) == 0)
238614f1b3e8SDimitry Andric matches.AppendString(
238714f1b3e8SDimitry Andric MakeMatch(prefix, def->children[i].name + match_prefix.size()));
238812bd4897SEd Maste }
238912bd4897SEd Maste }
239012bd4897SEd Maste }
2391f3fbd1c0SDimitry Andric
AutoComplete(CompletionRequest & request)2392ead24645SDimitry Andric void FormatEntity::AutoComplete(CompletionRequest &request) {
2393ead24645SDimitry Andric llvm::StringRef str = request.GetCursorArgumentPrefix();
239412bd4897SEd Maste
239512bd4897SEd Maste const size_t dollar_pos = str.rfind('$');
239614f1b3e8SDimitry Andric if (dollar_pos == llvm::StringRef::npos)
2397ead24645SDimitry Andric return;
239814f1b3e8SDimitry Andric
239912bd4897SEd Maste // Hitting TAB after $ at the end of the string add a "{"
240014f1b3e8SDimitry Andric if (dollar_pos == str.size() - 1) {
2401e81d9d49SDimitry Andric std::string match = str.str();
240212bd4897SEd Maste match.append("{");
240339be7ce2SDimitry Andric request.AddCompletion(match);
2404ead24645SDimitry Andric return;
240512bd4897SEd Maste }
240614f1b3e8SDimitry Andric
240714f1b3e8SDimitry Andric if (str[dollar_pos + 1] != '{')
2408ead24645SDimitry Andric return;
240914f1b3e8SDimitry Andric
241012bd4897SEd Maste const size_t close_pos = str.find('}', dollar_pos + 2);
241114f1b3e8SDimitry Andric if (close_pos != llvm::StringRef::npos)
2412ead24645SDimitry Andric return;
241314f1b3e8SDimitry Andric
241412bd4897SEd Maste const size_t format_pos = str.find('%', dollar_pos + 2);
241514f1b3e8SDimitry Andric if (format_pos != llvm::StringRef::npos)
2416ead24645SDimitry Andric return;
241714f1b3e8SDimitry Andric
241812bd4897SEd Maste llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
241914f1b3e8SDimitry Andric if (partial_variable.empty()) {
2420cfca06d7SDimitry Andric // Suggest all top level entities as we are just past "${"
242139be7ce2SDimitry Andric StringList new_matches;
242239be7ce2SDimitry Andric AddMatches(&g_root, str, llvm::StringRef(), new_matches);
242339be7ce2SDimitry Andric request.AddCompletions(new_matches);
2424ead24645SDimitry Andric return;
242512bd4897SEd Maste }
242614f1b3e8SDimitry Andric
242712bd4897SEd Maste // We have a partially specified variable, find it
242812bd4897SEd Maste llvm::StringRef remainder;
2429344a3780SDimitry Andric const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
243014f1b3e8SDimitry Andric if (!entry_def)
2431ead24645SDimitry Andric return;
243214f1b3e8SDimitry Andric
243312bd4897SEd Maste const size_t n = entry_def->num_children;
243412bd4897SEd Maste
243514f1b3e8SDimitry Andric if (remainder.empty()) {
243612bd4897SEd Maste // Exact match
243714f1b3e8SDimitry Andric if (n > 0) {
243812bd4897SEd Maste // "${thread.info" <TAB>
243939be7ce2SDimitry Andric request.AddCompletion(MakeMatch(str, "."));
244014f1b3e8SDimitry Andric } else {
244112bd4897SEd Maste // "${thread.id" <TAB>
244239be7ce2SDimitry Andric request.AddCompletion(MakeMatch(str, "}"));
244312bd4897SEd Maste }
2444ac9a064cSDimitry Andric } else if (remainder == ".") {
244512bd4897SEd Maste // "${thread." <TAB>
244639be7ce2SDimitry Andric StringList new_matches;
244739be7ce2SDimitry Andric AddMatches(entry_def, str, llvm::StringRef(), new_matches);
244839be7ce2SDimitry Andric request.AddCompletions(new_matches);
244914f1b3e8SDimitry Andric } else {
245012bd4897SEd Maste // We have a partial match
245112bd4897SEd Maste // "${thre" <TAB>
245239be7ce2SDimitry Andric StringList new_matches;
245339be7ce2SDimitry Andric AddMatches(entry_def, str, remainder, new_matches);
245439be7ce2SDimitry Andric request.AddCompletions(new_matches);
245512bd4897SEd Maste }
245612bd4897SEd Maste }
2457e3b55780SDimitry Andric
PrettyPrintFunctionArguments(Stream & out_stream,VariableList const & args,ExecutionContextScope * exe_scope)2458e3b55780SDimitry Andric void FormatEntity::PrettyPrintFunctionArguments(
2459e3b55780SDimitry Andric Stream &out_stream, VariableList const &args,
2460e3b55780SDimitry Andric ExecutionContextScope *exe_scope) {
2461e3b55780SDimitry Andric const size_t num_args = args.GetSize();
2462e3b55780SDimitry Andric for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2463e3b55780SDimitry Andric std::string buffer;
2464e3b55780SDimitry Andric
2465e3b55780SDimitry Andric VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2466e3b55780SDimitry Andric ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2467e3b55780SDimitry Andric StreamString ss;
2468e3b55780SDimitry Andric llvm::StringRef var_representation;
2469e3b55780SDimitry Andric const char *var_name = var_value_sp->GetName().GetCString();
2470e3b55780SDimitry Andric if (var_value_sp->GetCompilerType().IsValid()) {
2471e3b55780SDimitry Andric if (exe_scope && exe_scope->CalculateTarget())
2472e3b55780SDimitry Andric var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2473e3b55780SDimitry Andric exe_scope->CalculateTarget()
2474e3b55780SDimitry Andric ->TargetProperties::GetPreferDynamicValue(),
2475e3b55780SDimitry Andric exe_scope->CalculateTarget()
2476e3b55780SDimitry Andric ->TargetProperties::GetEnableSyntheticValue());
2477e3b55780SDimitry Andric if (var_value_sp->GetCompilerType().IsAggregateType() &&
2478e3b55780SDimitry Andric DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
2479e3b55780SDimitry Andric static StringSummaryFormat format(TypeSummaryImpl::Flags()
2480e3b55780SDimitry Andric .SetHideItemNames(false)
2481e3b55780SDimitry Andric .SetShowMembersOneLiner(true),
2482e3b55780SDimitry Andric "");
2483e3b55780SDimitry Andric format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2484e3b55780SDimitry Andric var_representation = buffer;
2485e3b55780SDimitry Andric } else
2486e3b55780SDimitry Andric var_value_sp->DumpPrintableRepresentation(
2487e3b55780SDimitry Andric ss,
2488e3b55780SDimitry Andric ValueObject::ValueObjectRepresentationStyle::
2489e3b55780SDimitry Andric eValueObjectRepresentationStyleSummary,
2490e3b55780SDimitry Andric eFormatDefault,
2491e3b55780SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
2492e3b55780SDimitry Andric }
2493e3b55780SDimitry Andric
2494e3b55780SDimitry Andric if (!ss.GetString().empty())
2495e3b55780SDimitry Andric var_representation = ss.GetString();
2496e3b55780SDimitry Andric if (arg_idx > 0)
2497e3b55780SDimitry Andric out_stream.PutCString(", ");
2498e3b55780SDimitry Andric if (var_value_sp->GetError().Success()) {
2499e3b55780SDimitry Andric if (!var_representation.empty())
2500e3b55780SDimitry Andric out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2501e3b55780SDimitry Andric else
2502e3b55780SDimitry Andric out_stream.Printf("%s=%s at %s", var_name,
2503e3b55780SDimitry Andric var_value_sp->GetTypeName().GetCString(),
2504e3b55780SDimitry Andric var_value_sp->GetLocationAsCString());
2505e3b55780SDimitry Andric } else
2506e3b55780SDimitry Andric out_stream.Printf("%s=<unavailable>", var_name);
2507e3b55780SDimitry Andric }
2508e3b55780SDimitry Andric }
2509b1c73532SDimitry Andric
Parse(const llvm::StringRef & format_str,Entry & entry)2510b1c73532SDimitry Andric Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2511b1c73532SDimitry Andric entry.Clear();
2512b1c73532SDimitry Andric entry.type = Entry::Type::Root;
2513b1c73532SDimitry Andric llvm::StringRef modifiable_format(format_str);
2514b1c73532SDimitry Andric return ParseInternal(modifiable_format, entry, 0);
2515b1c73532SDimitry Andric }
2516