15ffd83dbSDimitry Andric //===-- FormatEntity.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "lldb/Core/Address.h"
120b57cec5SDimitry Andric #include "lldb/Core/AddressRange.h"
130b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
140b57cec5SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectVariable.h"
180b57cec5SDimitry Andric #include "lldb/DataFormatters/DataVisualization.h"
190b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatClasses.h"
200b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
210b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
220b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
240b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
250b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/LineEntry.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
320b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
330b57cec5SDimitry Andric #include "lldb/Target/ExecutionContextScope.h"
340b57cec5SDimitry Andric #include "lldb/Target/Language.h"
350b57cec5SDimitry Andric #include "lldb/Target/Process.h"
360b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
370b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
380b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
390b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
400b57cec5SDimitry Andric #include "lldb/Target/Target.h"
410b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
420b57cec5SDimitry Andric #include "lldb/Utility/AnsiTerminal.h"
430b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
44*5f7ddb14SDimitry Andric #include "lldb/Utility/CompletionRequest.h"
450b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
460b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
470b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
480b57cec5SDimitry Andric #include "lldb/Utility/Logging.h"
490b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
50*5f7ddb14SDimitry Andric #include "lldb/Utility/Status.h"
510b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
520b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
530b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
540b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
550b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
560b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
570b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
580b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
590b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
600b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
610b57cec5SDimitry Andric
62*5f7ddb14SDimitry Andric #include <cctype>
63*5f7ddb14SDimitry Andric #include <cinttypes>
64*5f7ddb14SDimitry Andric #include <cstdio>
65*5f7ddb14SDimitry Andric #include <cstdlib>
66*5f7ddb14SDimitry Andric #include <cstring>
670b57cec5SDimitry Andric #include <memory>
680b57cec5SDimitry Andric #include <type_traits>
690b57cec5SDimitry Andric #include <utility>
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric namespace lldb_private {
720b57cec5SDimitry Andric class ScriptInterpreter;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric namespace lldb_private {
750b57cec5SDimitry Andric struct RegisterInfo;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric using namespace lldb;
790b57cec5SDimitry Andric using namespace lldb_private;
800b57cec5SDimitry Andric
81*5f7ddb14SDimitry Andric using Definition = lldb_private::FormatEntity::Entry::Definition;
82*5f7ddb14SDimitry Andric using Entry = FormatEntity::Entry;
83*5f7ddb14SDimitry Andric using EntryType = FormatEntity::Entry::Type;
84*5f7ddb14SDimitry Andric
850b57cec5SDimitry Andric enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
860b57cec5SDimitry Andric
87*5f7ddb14SDimitry Andric constexpr Definition g_string_entry[] = {
88*5f7ddb14SDimitry Andric Definition("*", EntryType::ParentString)};
890b57cec5SDimitry Andric
90*5f7ddb14SDimitry Andric constexpr Definition g_addr_entries[] = {
91*5f7ddb14SDimitry Andric Definition("load", EntryType::AddressLoad),
92*5f7ddb14SDimitry Andric Definition("file", EntryType::AddressFile)};
93*5f7ddb14SDimitry Andric
94*5f7ddb14SDimitry Andric constexpr Definition g_file_child_entries[] = {
95*5f7ddb14SDimitry Andric Definition("basename", EntryType::ParentNumber, FileKind::Basename),
96*5f7ddb14SDimitry Andric Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
97*5f7ddb14SDimitry Andric Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
98*5f7ddb14SDimitry Andric
99*5f7ddb14SDimitry Andric constexpr Definition g_frame_child_entries[] = {
100*5f7ddb14SDimitry Andric Definition("index", EntryType::FrameIndex),
101*5f7ddb14SDimitry Andric Definition("pc", EntryType::FrameRegisterPC),
102*5f7ddb14SDimitry Andric Definition("fp", EntryType::FrameRegisterFP),
103*5f7ddb14SDimitry Andric Definition("sp", EntryType::FrameRegisterSP),
104*5f7ddb14SDimitry Andric Definition("flags", EntryType::FrameRegisterFlags),
105*5f7ddb14SDimitry Andric Definition("no-debug", EntryType::FrameNoDebug),
106*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
107*5f7ddb14SDimitry Andric g_string_entry),
108*5f7ddb14SDimitry Andric Definition("is-artificial", EntryType::FrameIsArtificial),
1090b57cec5SDimitry Andric };
1100b57cec5SDimitry Andric
111*5f7ddb14SDimitry Andric constexpr Definition g_function_child_entries[] = {
112*5f7ddb14SDimitry Andric Definition("id", EntryType::FunctionID),
113*5f7ddb14SDimitry Andric Definition("name", EntryType::FunctionName),
114*5f7ddb14SDimitry Andric Definition("name-without-args", EntryType::FunctionNameNoArgs),
115*5f7ddb14SDimitry Andric Definition("name-with-args", EntryType::FunctionNameWithArgs),
116*5f7ddb14SDimitry Andric Definition("mangled-name", EntryType::FunctionMangledName),
117*5f7ddb14SDimitry Andric Definition("addr-offset", EntryType::FunctionAddrOffset),
118*5f7ddb14SDimitry Andric Definition("concrete-only-addr-offset-no-padding",
119*5f7ddb14SDimitry Andric EntryType::FunctionAddrOffsetConcrete),
120*5f7ddb14SDimitry Andric Definition("line-offset", EntryType::FunctionLineOffset),
121*5f7ddb14SDimitry Andric Definition("pc-offset", EntryType::FunctionPCOffset),
122*5f7ddb14SDimitry Andric Definition("initial-function", EntryType::FunctionInitial),
123*5f7ddb14SDimitry Andric Definition("changed", EntryType::FunctionChanged),
124*5f7ddb14SDimitry Andric Definition("is-optimized", EntryType::FunctionIsOptimized)};
1250b57cec5SDimitry Andric
126*5f7ddb14SDimitry Andric constexpr Definition g_line_child_entries[] = {
127*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
128*5f7ddb14SDimitry Andric g_file_child_entries),
129*5f7ddb14SDimitry Andric Definition("number", EntryType::LineEntryLineNumber),
130*5f7ddb14SDimitry Andric Definition("column", EntryType::LineEntryColumn),
131*5f7ddb14SDimitry Andric Definition("start-addr", EntryType::LineEntryStartAddress),
132*5f7ddb14SDimitry Andric Definition("end-addr", EntryType::LineEntryEndAddress),
1330b57cec5SDimitry Andric };
1340b57cec5SDimitry Andric
135*5f7ddb14SDimitry Andric constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
136*5f7ddb14SDimitry Andric "file", EntryType::ModuleFile, g_file_child_entries)};
1370b57cec5SDimitry Andric
138*5f7ddb14SDimitry Andric constexpr Definition g_process_child_entries[] = {
139*5f7ddb14SDimitry Andric Definition("id", EntryType::ProcessID),
140*5f7ddb14SDimitry Andric Definition("name", EntryType::ProcessFile, FileKind::Basename),
141*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
142*5f7ddb14SDimitry Andric g_file_child_entries)};
1430b57cec5SDimitry Andric
144*5f7ddb14SDimitry Andric constexpr Definition g_svar_child_entries[] = {
145*5f7ddb14SDimitry Andric Definition("*", EntryType::ParentString)};
1460b57cec5SDimitry Andric
147*5f7ddb14SDimitry Andric constexpr Definition g_var_child_entries[] = {
148*5f7ddb14SDimitry Andric Definition("*", EntryType::ParentString)};
1490b57cec5SDimitry Andric
150*5f7ddb14SDimitry Andric constexpr Definition g_thread_child_entries[] = {
151*5f7ddb14SDimitry Andric Definition("id", EntryType::ThreadID),
152*5f7ddb14SDimitry Andric Definition("protocol_id", EntryType::ThreadProtocolID),
153*5f7ddb14SDimitry Andric Definition("index", EntryType::ThreadIndexID),
154*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
155*5f7ddb14SDimitry Andric g_string_entry),
156*5f7ddb14SDimitry Andric Definition("queue", EntryType::ThreadQueue),
157*5f7ddb14SDimitry Andric Definition("name", EntryType::ThreadName),
158*5f7ddb14SDimitry Andric Definition("stop-reason", EntryType::ThreadStopReason),
159*5f7ddb14SDimitry Andric Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
160*5f7ddb14SDimitry Andric Definition("return-value", EntryType::ThreadReturnValue),
161*5f7ddb14SDimitry Andric Definition("completed-expression", EntryType::ThreadCompletedExpression)};
1620b57cec5SDimitry Andric
163*5f7ddb14SDimitry Andric constexpr Definition g_target_child_entries[] = {
164*5f7ddb14SDimitry Andric Definition("arch", EntryType::TargetArch)};
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric #define _TO_STR2(_val) #_val
1670b57cec5SDimitry Andric #define _TO_STR(_val) _TO_STR2(_val)
1680b57cec5SDimitry Andric
169*5f7ddb14SDimitry Andric constexpr Definition g_ansi_fg_entries[] = {
170*5f7ddb14SDimitry Andric Definition("black",
1710b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
172*5f7ddb14SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
173*5f7ddb14SDimitry Andric Definition("green",
1740b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
175*5f7ddb14SDimitry Andric Definition("yellow",
1760b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
177*5f7ddb14SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
178*5f7ddb14SDimitry Andric Definition("purple",
1790b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
180*5f7ddb14SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
181*5f7ddb14SDimitry Andric Definition("white",
1820b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric
185*5f7ddb14SDimitry Andric constexpr Definition g_ansi_bg_entries[] = {
186*5f7ddb14SDimitry Andric Definition("black",
1870b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
188*5f7ddb14SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
189*5f7ddb14SDimitry Andric Definition("green",
1900b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
191*5f7ddb14SDimitry Andric Definition("yellow",
1920b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
193*5f7ddb14SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
194*5f7ddb14SDimitry Andric Definition("purple",
1950b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
196*5f7ddb14SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
197*5f7ddb14SDimitry Andric Definition("white",
1980b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
1990b57cec5SDimitry Andric };
2000b57cec5SDimitry Andric
201*5f7ddb14SDimitry Andric constexpr Definition g_ansi_entries[] = {
202*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
203*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
204*5f7ddb14SDimitry Andric Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
205*5f7ddb14SDimitry Andric Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
206*5f7ddb14SDimitry Andric Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
207*5f7ddb14SDimitry Andric Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
208*5f7ddb14SDimitry Andric Definition("underline",
2090b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
210*5f7ddb14SDimitry Andric Definition("slow-blink",
2110b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
212*5f7ddb14SDimitry Andric Definition("fast-blink",
2130b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
214*5f7ddb14SDimitry Andric Definition("negative",
2150b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
216*5f7ddb14SDimitry Andric Definition("conceal",
2170b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
218*5f7ddb14SDimitry Andric Definition("crossed-out",
2190b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
2200b57cec5SDimitry Andric };
2210b57cec5SDimitry Andric
222*5f7ddb14SDimitry Andric constexpr Definition g_script_child_entries[] = {
223*5f7ddb14SDimitry Andric Definition("frame", EntryType::ScriptFrame),
224*5f7ddb14SDimitry Andric Definition("process", EntryType::ScriptProcess),
225*5f7ddb14SDimitry Andric Definition("target", EntryType::ScriptTarget),
226*5f7ddb14SDimitry Andric Definition("thread", EntryType::ScriptThread),
227*5f7ddb14SDimitry Andric Definition("var", EntryType::ScriptVariable),
228*5f7ddb14SDimitry Andric Definition("svar", EntryType::ScriptVariableSynthetic),
229*5f7ddb14SDimitry Andric Definition("thread", EntryType::ScriptThread)};
2300b57cec5SDimitry Andric
231*5f7ddb14SDimitry Andric constexpr Definition g_top_level_entries[] = {
232*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
233*5f7ddb14SDimitry Andric g_addr_entries),
234*5f7ddb14SDimitry Andric Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
235*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
236*5f7ddb14SDimitry Andric Definition("current-pc-arrow", EntryType::CurrentPCArrow),
237*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::File,
238*5f7ddb14SDimitry Andric g_file_child_entries),
239*5f7ddb14SDimitry Andric Definition("language", EntryType::Lang),
240*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("frame", EntryType::Invalid,
241*5f7ddb14SDimitry Andric g_frame_child_entries),
242*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("function", EntryType::Invalid,
243*5f7ddb14SDimitry Andric g_function_child_entries),
244*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("line", EntryType::Invalid,
245*5f7ddb14SDimitry Andric g_line_child_entries),
246*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("module", EntryType::Invalid,
247*5f7ddb14SDimitry Andric g_module_child_entries),
248*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("process", EntryType::Invalid,
249*5f7ddb14SDimitry Andric g_process_child_entries),
250*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("script", EntryType::Invalid,
251*5f7ddb14SDimitry Andric g_script_child_entries),
252*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
253*5f7ddb14SDimitry Andric g_svar_child_entries, true),
254*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("thread", EntryType::Invalid,
255*5f7ddb14SDimitry Andric g_thread_child_entries),
256*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("target", EntryType::Invalid,
257*5f7ddb14SDimitry Andric g_target_child_entries),
258*5f7ddb14SDimitry Andric Entry::DefinitionWithChildren("var", EntryType::Variable,
259*5f7ddb14SDimitry Andric g_var_child_entries, true)};
2600b57cec5SDimitry Andric
261*5f7ddb14SDimitry Andric constexpr Definition g_root = Entry::DefinitionWithChildren(
262*5f7ddb14SDimitry Andric "<root>", EntryType::Root, g_top_level_entries);
2630b57cec5SDimitry Andric
Entry(llvm::StringRef s)2640b57cec5SDimitry Andric FormatEntity::Entry::Entry(llvm::StringRef s)
2650b57cec5SDimitry Andric : string(s.data(), s.size()), printf_format(), children(),
266*5f7ddb14SDimitry Andric type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
2670b57cec5SDimitry Andric
Entry(char ch)2680b57cec5SDimitry Andric FormatEntity::Entry::Entry(char ch)
269*5f7ddb14SDimitry Andric : string(1, ch), printf_format(), children(), type(Type::String),
270*5f7ddb14SDimitry Andric fmt(lldb::eFormatDefault), number(0), deref(false) {}
2710b57cec5SDimitry Andric
AppendChar(char ch)2720b57cec5SDimitry Andric void FormatEntity::Entry::AppendChar(char ch) {
2730b57cec5SDimitry Andric if (children.empty() || children.back().type != Entry::Type::String)
2740b57cec5SDimitry Andric children.push_back(Entry(ch));
2750b57cec5SDimitry Andric else
2760b57cec5SDimitry Andric children.back().string.append(1, ch);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric
AppendText(const llvm::StringRef & s)2790b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
2800b57cec5SDimitry Andric if (children.empty() || children.back().type != Entry::Type::String)
2810b57cec5SDimitry Andric children.push_back(Entry(s));
2820b57cec5SDimitry Andric else
2830b57cec5SDimitry Andric children.back().string.append(s.data(), s.size());
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric
AppendText(const char * cstr)2860b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const char *cstr) {
2870b57cec5SDimitry Andric return AppendText(llvm::StringRef(cstr));
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric
Parse(const llvm::StringRef & format_str,Entry & entry)2900b57cec5SDimitry Andric Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2910b57cec5SDimitry Andric entry.Clear();
2920b57cec5SDimitry Andric entry.type = Entry::Type::Root;
2930b57cec5SDimitry Andric llvm::StringRef modifiable_format(format_str);
2940b57cec5SDimitry Andric return ParseInternal(modifiable_format, entry, 0);
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric #define ENUM_TO_CSTR(eee) \
2980b57cec5SDimitry Andric case FormatEntity::Entry::Type::eee: \
2990b57cec5SDimitry Andric return #eee
3000b57cec5SDimitry Andric
TypeToCString(Type t)3010b57cec5SDimitry Andric const char *FormatEntity::Entry::TypeToCString(Type t) {
3020b57cec5SDimitry Andric switch (t) {
3030b57cec5SDimitry Andric ENUM_TO_CSTR(Invalid);
3040b57cec5SDimitry Andric ENUM_TO_CSTR(ParentNumber);
3050b57cec5SDimitry Andric ENUM_TO_CSTR(ParentString);
3060b57cec5SDimitry Andric ENUM_TO_CSTR(EscapeCode);
3070b57cec5SDimitry Andric ENUM_TO_CSTR(Root);
3080b57cec5SDimitry Andric ENUM_TO_CSTR(String);
3090b57cec5SDimitry Andric ENUM_TO_CSTR(Scope);
3100b57cec5SDimitry Andric ENUM_TO_CSTR(Variable);
3110b57cec5SDimitry Andric ENUM_TO_CSTR(VariableSynthetic);
3120b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptVariable);
3130b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptVariableSynthetic);
3140b57cec5SDimitry Andric ENUM_TO_CSTR(AddressLoad);
3150b57cec5SDimitry Andric ENUM_TO_CSTR(AddressFile);
3160b57cec5SDimitry Andric ENUM_TO_CSTR(AddressLoadOrFile);
3170b57cec5SDimitry Andric ENUM_TO_CSTR(ProcessID);
3180b57cec5SDimitry Andric ENUM_TO_CSTR(ProcessFile);
3190b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptProcess);
3200b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadID);
3210b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadProtocolID);
3220b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadIndexID);
3230b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadName);
3240b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadQueue);
3250b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadStopReason);
3265ffd83dbSDimitry Andric ENUM_TO_CSTR(ThreadStopReasonRaw);
3270b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadReturnValue);
3280b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadCompletedExpression);
3290b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptThread);
3300b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadInfo);
3310b57cec5SDimitry Andric ENUM_TO_CSTR(TargetArch);
3320b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptTarget);
3330b57cec5SDimitry Andric ENUM_TO_CSTR(ModuleFile);
3340b57cec5SDimitry Andric ENUM_TO_CSTR(File);
3350b57cec5SDimitry Andric ENUM_TO_CSTR(Lang);
3360b57cec5SDimitry Andric ENUM_TO_CSTR(FrameIndex);
3370b57cec5SDimitry Andric ENUM_TO_CSTR(FrameNoDebug);
3380b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterPC);
3390b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterSP);
3400b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterFP);
3410b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterFlags);
3420b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterByName);
3430b57cec5SDimitry Andric ENUM_TO_CSTR(FrameIsArtificial);
3440b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptFrame);
3450b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionID);
3460b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionDidChange);
3470b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionInitialFunction);
3480b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionName);
3490b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionNameWithArgs);
3500b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionNameNoArgs);
351480093f4SDimitry Andric ENUM_TO_CSTR(FunctionMangledName);
3520b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionAddrOffset);
3530b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
3540b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionLineOffset);
3550b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionPCOffset);
3560b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionInitial);
3570b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionChanged);
3580b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionIsOptimized);
3590b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryFile);
3600b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryLineNumber);
3610b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryColumn);
3620b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryStartAddress);
3630b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryEndAddress);
3640b57cec5SDimitry Andric ENUM_TO_CSTR(CurrentPCArrow);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric return "???";
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric #undef ENUM_TO_CSTR
3700b57cec5SDimitry Andric
Dump(Stream & s,int depth) const3710b57cec5SDimitry Andric void FormatEntity::Entry::Dump(Stream &s, int depth) const {
3720b57cec5SDimitry Andric s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
3730b57cec5SDimitry Andric if (fmt != eFormatDefault)
3740b57cec5SDimitry Andric s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
3750b57cec5SDimitry Andric if (!string.empty())
3760b57cec5SDimitry Andric s.Printf("string = \"%s\"", string.c_str());
3770b57cec5SDimitry Andric if (!printf_format.empty())
3780b57cec5SDimitry Andric s.Printf("printf_format = \"%s\"", printf_format.c_str());
3790b57cec5SDimitry Andric if (number != 0)
3800b57cec5SDimitry Andric s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
3810b57cec5SDimitry Andric if (deref)
3820b57cec5SDimitry Andric s.Printf("deref = true, ");
3830b57cec5SDimitry Andric s.EOL();
3840b57cec5SDimitry Andric for (const auto &child : children) {
3850b57cec5SDimitry Andric child.Dump(s, depth + 1);
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric template <typename T>
RunScriptFormatKeyword(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,T t,const char * script_function_name)3900b57cec5SDimitry Andric static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
3910b57cec5SDimitry Andric const ExecutionContext *exe_ctx, T t,
3920b57cec5SDimitry Andric const char *script_function_name) {
3930b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric if (target) {
3960b57cec5SDimitry Andric ScriptInterpreter *script_interpreter =
3970b57cec5SDimitry Andric target->GetDebugger().GetScriptInterpreter();
3980b57cec5SDimitry Andric if (script_interpreter) {
3990b57cec5SDimitry Andric Status error;
4000b57cec5SDimitry Andric std::string script_output;
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
4030b57cec5SDimitry Andric script_output, error) &&
4040b57cec5SDimitry Andric error.Success()) {
4050b57cec5SDimitry Andric s.Printf("%s", script_output.c_str());
4060b57cec5SDimitry Andric return true;
4070b57cec5SDimitry Andric } else {
4080b57cec5SDimitry Andric s.Printf("<error: %s>", error.AsCString());
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric return false;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
DumpAddressAndContent(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & addr,bool print_file_addr_or_load_addr)415480093f4SDimitry Andric static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc,
416480093f4SDimitry Andric const ExecutionContext *exe_ctx,
417480093f4SDimitry Andric const Address &addr,
4180b57cec5SDimitry Andric bool print_file_addr_or_load_addr) {
4190b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4200b57cec5SDimitry Andric addr_t vaddr = LLDB_INVALID_ADDRESS;
4210b57cec5SDimitry Andric if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
4220b57cec5SDimitry Andric vaddr = addr.GetLoadAddress(target);
4230b57cec5SDimitry Andric if (vaddr == LLDB_INVALID_ADDRESS)
4240b57cec5SDimitry Andric vaddr = addr.GetFileAddress();
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric if (vaddr != LLDB_INVALID_ADDRESS) {
4270b57cec5SDimitry Andric int addr_width = 0;
4280b57cec5SDimitry Andric if (exe_ctx && target) {
4290b57cec5SDimitry Andric addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric if (addr_width == 0)
4320b57cec5SDimitry Andric addr_width = 16;
4330b57cec5SDimitry Andric if (print_file_addr_or_load_addr) {
4340b57cec5SDimitry Andric ExecutionContextScope *exe_scope = nullptr;
4350b57cec5SDimitry Andric if (exe_ctx)
4360b57cec5SDimitry Andric exe_scope = exe_ctx->GetBestExecutionContextScope();
4370b57cec5SDimitry Andric addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
4380b57cec5SDimitry Andric Address::DumpStyleModuleWithFileAddress, 0);
4390b57cec5SDimitry Andric } else {
4400b57cec5SDimitry Andric s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric return true;
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric return false;
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric
DumpAddressOffsetFromFunction(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & format_addr,bool concrete_only,bool no_padding,bool print_zero_offsets)4470b57cec5SDimitry Andric static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
4480b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
4490b57cec5SDimitry Andric const Address &format_addr,
4500b57cec5SDimitry Andric bool concrete_only, bool no_padding,
4510b57cec5SDimitry Andric bool print_zero_offsets) {
4520b57cec5SDimitry Andric if (format_addr.IsValid()) {
4530b57cec5SDimitry Andric Address func_addr;
4540b57cec5SDimitry Andric
4550b57cec5SDimitry Andric if (sc) {
4560b57cec5SDimitry Andric if (sc->function) {
4570b57cec5SDimitry Andric func_addr = sc->function->GetAddressRange().GetBaseAddress();
4580b57cec5SDimitry Andric if (sc->block && !concrete_only) {
4590b57cec5SDimitry Andric // Check to make sure we aren't in an inline function. If we are, use
4600b57cec5SDimitry Andric // the inline block range that contains "format_addr" since blocks
4610b57cec5SDimitry Andric // can be discontiguous.
4620b57cec5SDimitry Andric Block *inline_block = sc->block->GetContainingInlinedBlock();
4630b57cec5SDimitry Andric AddressRange inline_range;
4640b57cec5SDimitry Andric if (inline_block && inline_block->GetRangeContainingAddress(
4650b57cec5SDimitry Andric format_addr, inline_range))
4660b57cec5SDimitry Andric func_addr = inline_range.GetBaseAddress();
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric } else if (sc->symbol && sc->symbol->ValueIsAddress())
4690b57cec5SDimitry Andric func_addr = sc->symbol->GetAddressRef();
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric
4720b57cec5SDimitry Andric if (func_addr.IsValid()) {
4730b57cec5SDimitry Andric const char *addr_offset_padding = no_padding ? "" : " ";
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric if (func_addr.GetSection() == format_addr.GetSection()) {
4760b57cec5SDimitry Andric addr_t func_file_addr = func_addr.GetFileAddress();
4770b57cec5SDimitry Andric addr_t addr_file_addr = format_addr.GetFileAddress();
4780b57cec5SDimitry Andric if (addr_file_addr > func_file_addr ||
4790b57cec5SDimitry Andric (addr_file_addr == func_file_addr && print_zero_offsets)) {
4800b57cec5SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4810b57cec5SDimitry Andric addr_file_addr - func_file_addr);
4820b57cec5SDimitry Andric } else if (addr_file_addr < func_file_addr) {
4830b57cec5SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4840b57cec5SDimitry Andric func_file_addr - addr_file_addr);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric return true;
4870b57cec5SDimitry Andric } else {
4880b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4890b57cec5SDimitry Andric if (target) {
4900b57cec5SDimitry Andric addr_t func_load_addr = func_addr.GetLoadAddress(target);
4910b57cec5SDimitry Andric addr_t addr_load_addr = format_addr.GetLoadAddress(target);
4920b57cec5SDimitry Andric if (addr_load_addr > func_load_addr ||
4930b57cec5SDimitry Andric (addr_load_addr == func_load_addr && print_zero_offsets)) {
4940b57cec5SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4950b57cec5SDimitry Andric addr_load_addr - func_load_addr);
4960b57cec5SDimitry Andric } else if (addr_load_addr < func_load_addr) {
4970b57cec5SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4980b57cec5SDimitry Andric func_load_addr - addr_load_addr);
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric return true;
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric return false;
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
ScanBracketedRange(llvm::StringRef subpath,size_t & close_bracket_index,const char * & var_name_final_if_array_range,int64_t & index_lower,int64_t & index_higher)5080b57cec5SDimitry Andric static bool ScanBracketedRange(llvm::StringRef subpath,
5090b57cec5SDimitry Andric size_t &close_bracket_index,
5100b57cec5SDimitry Andric const char *&var_name_final_if_array_range,
5110b57cec5SDimitry Andric int64_t &index_lower, int64_t &index_higher) {
5120b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
5130b57cec5SDimitry Andric close_bracket_index = llvm::StringRef::npos;
5140b57cec5SDimitry Andric const size_t open_bracket_index = subpath.find('[');
5150b57cec5SDimitry Andric if (open_bracket_index == llvm::StringRef::npos) {
5169dba64beSDimitry Andric LLDB_LOGF(log,
5179dba64beSDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
5180b57cec5SDimitry Andric return false;
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric close_bracket_index = subpath.find(']', open_bracket_index + 1);
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric if (close_bracket_index == llvm::StringRef::npos) {
5249dba64beSDimitry Andric LLDB_LOGF(log,
5259dba64beSDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
5260b57cec5SDimitry Andric return false;
5270b57cec5SDimitry Andric } else {
5280b57cec5SDimitry Andric var_name_final_if_array_range = subpath.data() + open_bracket_index;
5290b57cec5SDimitry Andric
5300b57cec5SDimitry Andric if (close_bracket_index - open_bracket_index == 1) {
5319dba64beSDimitry Andric LLDB_LOGF(
5329dba64beSDimitry Andric log,
5330b57cec5SDimitry Andric "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
5340b57cec5SDimitry Andric index_lower = 0;
5350b57cec5SDimitry Andric } else {
5360b57cec5SDimitry Andric const size_t separator_index = subpath.find('-', open_bracket_index + 1);
5370b57cec5SDimitry Andric
5380b57cec5SDimitry Andric if (separator_index == llvm::StringRef::npos) {
5390b57cec5SDimitry Andric const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5400b57cec5SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5410b57cec5SDimitry Andric index_higher = index_lower;
5429dba64beSDimitry Andric LLDB_LOGF(log,
5439dba64beSDimitry Andric "[ScanBracketedRange] [%" PRId64
5440b57cec5SDimitry Andric "] detected, high index is same",
5450b57cec5SDimitry Andric index_lower);
5460b57cec5SDimitry Andric } else {
5470b57cec5SDimitry Andric const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5480b57cec5SDimitry Andric const char *index_higher_cstr = subpath.data() + separator_index + 1;
5490b57cec5SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5500b57cec5SDimitry Andric index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
5519dba64beSDimitry Andric LLDB_LOGF(log,
5529dba64beSDimitry Andric "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
5530b57cec5SDimitry Andric index_lower, index_higher);
5540b57cec5SDimitry Andric }
5550b57cec5SDimitry Andric if (index_lower > index_higher && index_higher > 0) {
5569dba64beSDimitry Andric LLDB_LOGF(log, "[ScanBracketedRange] swapping indices");
5570b57cec5SDimitry Andric const int64_t temp = index_lower;
5580b57cec5SDimitry Andric index_lower = index_higher;
5590b57cec5SDimitry Andric index_higher = temp;
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric return true;
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric
DumpFile(Stream & s,const FileSpec & file,FileKind file_kind)5660b57cec5SDimitry Andric static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
5670b57cec5SDimitry Andric switch (file_kind) {
5680b57cec5SDimitry Andric case FileKind::FileError:
5690b57cec5SDimitry Andric break;
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric case FileKind::Basename:
5720b57cec5SDimitry Andric if (file.GetFilename()) {
5730b57cec5SDimitry Andric s << file.GetFilename();
5740b57cec5SDimitry Andric return true;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric break;
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric case FileKind::Dirname:
5790b57cec5SDimitry Andric if (file.GetDirectory()) {
5800b57cec5SDimitry Andric s << file.GetDirectory();
5810b57cec5SDimitry Andric return true;
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric break;
5840b57cec5SDimitry Andric
5850b57cec5SDimitry Andric case FileKind::Fullpath:
5860b57cec5SDimitry Andric if (file) {
5870b57cec5SDimitry Andric s << file;
5880b57cec5SDimitry Andric return true;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric break;
5910b57cec5SDimitry Andric }
5920b57cec5SDimitry Andric return false;
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric
DumpRegister(Stream & s,StackFrame * frame,RegisterKind reg_kind,uint32_t reg_num,Format format)5950b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
596*5f7ddb14SDimitry Andric uint32_t reg_num, Format format) {
5970b57cec5SDimitry Andric if (frame) {
5980b57cec5SDimitry Andric RegisterContext *reg_ctx = frame->GetRegisterContext().get();
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric if (reg_ctx) {
6010b57cec5SDimitry Andric const uint32_t lldb_reg_num =
6020b57cec5SDimitry Andric reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
6030b57cec5SDimitry Andric if (lldb_reg_num != LLDB_INVALID_REGNUM) {
6040b57cec5SDimitry Andric const RegisterInfo *reg_info =
6050b57cec5SDimitry Andric reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
6060b57cec5SDimitry Andric if (reg_info) {
6070b57cec5SDimitry Andric RegisterValue reg_value;
6080b57cec5SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
6090b57cec5SDimitry Andric DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
6100b57cec5SDimitry Andric return true;
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric return false;
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric
ExpandIndexedExpression(ValueObject * valobj,size_t index,bool deref_pointer)6190b57cec5SDimitry Andric static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
6200b57cec5SDimitry Andric bool deref_pointer) {
6210b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
6220b57cec5SDimitry Andric const char *ptr_deref_format = "[%d]";
6230b57cec5SDimitry Andric std::string ptr_deref_buffer(10, 0);
6240b57cec5SDimitry Andric ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
6259dba64beSDimitry Andric LLDB_LOGF(log, "[ExpandIndexedExpression] name to deref: %s",
6260b57cec5SDimitry Andric ptr_deref_buffer.c_str());
6270b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions options;
6280b57cec5SDimitry Andric ValueObject::ExpressionPathEndResultType final_value_type;
6290b57cec5SDimitry Andric ValueObject::ExpressionPathScanEndReason reason_to_stop;
6300b57cec5SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
6310b57cec5SDimitry Andric (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
6320b57cec5SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
6330b57cec5SDimitry Andric ValueObjectSP item = valobj->GetValueForExpressionPath(
6340b57cec5SDimitry Andric ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options,
6350b57cec5SDimitry Andric &what_next);
6360b57cec5SDimitry Andric if (!item) {
6379dba64beSDimitry Andric LLDB_LOGF(log,
6389dba64beSDimitry Andric "[ExpandIndexedExpression] ERROR: why stopping = %d,"
6390b57cec5SDimitry Andric " final_value_type %d",
6400b57cec5SDimitry Andric reason_to_stop, final_value_type);
6410b57cec5SDimitry Andric } else {
6429dba64beSDimitry Andric LLDB_LOGF(log,
6439dba64beSDimitry Andric "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
6440b57cec5SDimitry Andric " final_value_type %d",
6450b57cec5SDimitry Andric reason_to_stop, final_value_type);
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric return item;
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric
ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)6500b57cec5SDimitry Andric static char ConvertValueObjectStyleToChar(
6510b57cec5SDimitry Andric ValueObject::ValueObjectRepresentationStyle style) {
6520b57cec5SDimitry Andric switch (style) {
6530b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
6540b57cec5SDimitry Andric return '@';
6550b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleValue:
6560b57cec5SDimitry Andric return 'V';
6570b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLocation:
6580b57cec5SDimitry Andric return 'L';
6590b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleSummary:
6600b57cec5SDimitry Andric return 'S';
6610b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleChildrenCount:
6620b57cec5SDimitry Andric return '#';
6630b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleType:
6640b57cec5SDimitry Andric return 'T';
6650b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleName:
6660b57cec5SDimitry Andric return 'N';
6670b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleExpressionPath:
6680b57cec5SDimitry Andric return '>';
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric return '\0';
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
DumpValue(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const FormatEntity::Entry & entry,ValueObject * valobj)6730b57cec5SDimitry Andric static bool DumpValue(Stream &s, const SymbolContext *sc,
6740b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
6750b57cec5SDimitry Andric const FormatEntity::Entry &entry, ValueObject *valobj) {
6760b57cec5SDimitry Andric if (valobj == nullptr)
6770b57cec5SDimitry Andric return false;
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
6800b57cec5SDimitry Andric Format custom_format = eFormatInvalid;
6810b57cec5SDimitry Andric ValueObject::ValueObjectRepresentationStyle val_obj_display =
6820b57cec5SDimitry Andric entry.string.empty()
6830b57cec5SDimitry Andric ? ValueObject::eValueObjectRepresentationStyleValue
6840b57cec5SDimitry Andric : ValueObject::eValueObjectRepresentationStyleSummary;
6850b57cec5SDimitry Andric
6860b57cec5SDimitry Andric bool do_deref_pointer = entry.deref;
6870b57cec5SDimitry Andric bool is_script = false;
6880b57cec5SDimitry Andric switch (entry.type) {
6890b57cec5SDimitry Andric case FormatEntity::Entry::Type::ScriptVariable:
6900b57cec5SDimitry Andric is_script = true;
6910b57cec5SDimitry Andric break;
6920b57cec5SDimitry Andric
6930b57cec5SDimitry Andric case FormatEntity::Entry::Type::Variable:
6940b57cec5SDimitry Andric custom_format = entry.fmt;
6950b57cec5SDimitry Andric val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
6960b57cec5SDimitry Andric break;
6970b57cec5SDimitry Andric
6980b57cec5SDimitry Andric case FormatEntity::Entry::Type::ScriptVariableSynthetic:
6990b57cec5SDimitry Andric is_script = true;
7000b57cec5SDimitry Andric LLVM_FALLTHROUGH;
7010b57cec5SDimitry Andric case FormatEntity::Entry::Type::VariableSynthetic:
7020b57cec5SDimitry Andric custom_format = entry.fmt;
7030b57cec5SDimitry Andric val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
7040b57cec5SDimitry Andric if (!valobj->IsSynthetic()) {
7050b57cec5SDimitry Andric valobj = valobj->GetSyntheticValue().get();
7060b57cec5SDimitry Andric if (valobj == nullptr)
7070b57cec5SDimitry Andric return false;
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric break;
7100b57cec5SDimitry Andric
7110b57cec5SDimitry Andric default:
7120b57cec5SDimitry Andric return false;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric if (valobj == nullptr)
7160b57cec5SDimitry Andric return false;
7170b57cec5SDimitry Andric
7180b57cec5SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
7190b57cec5SDimitry Andric (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
7200b57cec5SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
7210b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions options;
7220b57cec5SDimitry Andric options.DontCheckDotVsArrowSyntax()
7230b57cec5SDimitry Andric .DoAllowBitfieldSyntax()
7240b57cec5SDimitry Andric .DoAllowFragileIVar()
7250b57cec5SDimitry Andric .SetSyntheticChildrenTraversal(
7260b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions::
7270b57cec5SDimitry Andric SyntheticChildrenTraversal::Both);
7280b57cec5SDimitry Andric ValueObject *target = nullptr;
7290b57cec5SDimitry Andric const char *var_name_final_if_array_range = nullptr;
7300b57cec5SDimitry Andric size_t close_bracket_index = llvm::StringRef::npos;
7310b57cec5SDimitry Andric int64_t index_lower = -1;
7320b57cec5SDimitry Andric int64_t index_higher = -1;
7330b57cec5SDimitry Andric bool is_array_range = false;
7340b57cec5SDimitry Andric bool was_plain_var = false;
7350b57cec5SDimitry Andric bool was_var_format = false;
7360b57cec5SDimitry Andric bool was_var_indexed = false;
7370b57cec5SDimitry Andric ValueObject::ExpressionPathScanEndReason reason_to_stop =
7380b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString;
7390b57cec5SDimitry Andric ValueObject::ExpressionPathEndResultType final_value_type =
7400b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypePlain;
7410b57cec5SDimitry Andric
7420b57cec5SDimitry Andric if (is_script) {
7430b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric
7460b57cec5SDimitry Andric llvm::StringRef subpath(entry.string);
7470b57cec5SDimitry Andric // simplest case ${var}, just print valobj's value
7480b57cec5SDimitry Andric if (entry.string.empty()) {
7490b57cec5SDimitry Andric if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
7500b57cec5SDimitry Andric entry.number == ValueObject::eValueObjectRepresentationStyleValue)
7510b57cec5SDimitry Andric was_plain_var = true;
7520b57cec5SDimitry Andric else
7530b57cec5SDimitry Andric was_var_format = true;
7540b57cec5SDimitry Andric target = valobj;
7550b57cec5SDimitry Andric } else // this is ${var.something} or multiple .something nested
7560b57cec5SDimitry Andric {
7570b57cec5SDimitry Andric if (entry.string[0] == '[')
7580b57cec5SDimitry Andric was_var_indexed = true;
7590b57cec5SDimitry Andric ScanBracketedRange(subpath, close_bracket_index,
7600b57cec5SDimitry Andric var_name_final_if_array_range, index_lower,
7610b57cec5SDimitry Andric index_higher);
7620b57cec5SDimitry Andric
7630b57cec5SDimitry Andric Status error;
7640b57cec5SDimitry Andric
7650b57cec5SDimitry Andric const std::string &expr_path = entry.string;
7660b57cec5SDimitry Andric
7679dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s",
7680b57cec5SDimitry Andric expr_path.c_str());
7690b57cec5SDimitry Andric
7700b57cec5SDimitry Andric target =
7710b57cec5SDimitry Andric valobj
7720b57cec5SDimitry Andric ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
7730b57cec5SDimitry Andric &final_value_type, options, &what_next)
7740b57cec5SDimitry Andric .get();
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric if (!target) {
7779dba64beSDimitry Andric LLDB_LOGF(log,
7789dba64beSDimitry Andric "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
7790b57cec5SDimitry Andric " final_value_type %d",
7800b57cec5SDimitry Andric reason_to_stop, final_value_type);
7810b57cec5SDimitry Andric return false;
7820b57cec5SDimitry Andric } else {
7839dba64beSDimitry Andric LLDB_LOGF(log,
7849dba64beSDimitry Andric "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
7850b57cec5SDimitry Andric " final_value_type %d",
7860b57cec5SDimitry Andric reason_to_stop, final_value_type);
7870b57cec5SDimitry Andric target = target
7880b57cec5SDimitry Andric ->GetQualifiedRepresentationIfAvailable(
7890b57cec5SDimitry Andric target->GetDynamicValueType(), true)
7900b57cec5SDimitry Andric .get();
7910b57cec5SDimitry Andric }
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric
7940b57cec5SDimitry Andric is_array_range =
7950b57cec5SDimitry Andric (final_value_type ==
7960b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypeBoundedRange ||
7970b57cec5SDimitry Andric final_value_type ==
7980b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypeUnboundedRange);
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric do_deref_pointer =
8010b57cec5SDimitry Andric (what_next == ValueObject::eExpressionPathAftermathDereference);
8020b57cec5SDimitry Andric
8030b57cec5SDimitry Andric if (do_deref_pointer && !is_array_range) {
8040b57cec5SDimitry Andric // I have not deref-ed yet, let's do it
8050b57cec5SDimitry Andric // this happens when we are not going through
8060b57cec5SDimitry Andric // GetValueForVariableExpressionPath to get to the target ValueObject
8070b57cec5SDimitry Andric Status error;
8080b57cec5SDimitry Andric target = target->Dereference(error).get();
8090b57cec5SDimitry Andric if (error.Fail()) {
8109dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
8110b57cec5SDimitry Andric error.AsCString("unknown"));
8120b57cec5SDimitry Andric return false;
8130b57cec5SDimitry Andric }
8140b57cec5SDimitry Andric do_deref_pointer = false;
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric if (!target) {
8189dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
8190b57cec5SDimitry Andric "prompt expression");
8200b57cec5SDimitry Andric return false;
8210b57cec5SDimitry Andric }
8220b57cec5SDimitry Andric
8230b57cec5SDimitry Andric // we do not want to use the summary for a bitfield of type T:n if we were
8240b57cec5SDimitry Andric // originally dealing with just a T - that would get us into an endless
8250b57cec5SDimitry Andric // recursion
8260b57cec5SDimitry Andric if (target->IsBitfield() && was_var_indexed) {
8270b57cec5SDimitry Andric // TODO: check for a (T:n)-specific summary - we should still obey that
8280b57cec5SDimitry Andric StreamString bitfield_name;
8290b57cec5SDimitry Andric bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
8300b57cec5SDimitry Andric target->GetBitfieldBitSize());
8310b57cec5SDimitry Andric auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
8320b57cec5SDimitry Andric bitfield_name.GetString(), false);
8330b57cec5SDimitry Andric if (val_obj_display ==
8340b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary &&
8350b57cec5SDimitry Andric !DataVisualization::GetSummaryForType(type_sp))
8360b57cec5SDimitry Andric val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric // TODO use flags for these
8400b57cec5SDimitry Andric const uint32_t type_info_flags =
8410b57cec5SDimitry Andric target->GetCompilerType().GetTypeInfo(nullptr);
8420b57cec5SDimitry Andric bool is_array = (type_info_flags & eTypeIsArray) != 0;
8430b57cec5SDimitry Andric bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
8440b57cec5SDimitry Andric bool is_aggregate = target->GetCompilerType().IsAggregateType();
8450b57cec5SDimitry Andric
8460b57cec5SDimitry Andric if ((is_array || is_pointer) && (!is_array_range) &&
8470b57cec5SDimitry Andric val_obj_display ==
8480b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue) // this should be
8490b57cec5SDimitry Andric // wrong, but there
8500b57cec5SDimitry Andric // are some
8510b57cec5SDimitry Andric // exceptions
8520b57cec5SDimitry Andric {
8530b57cec5SDimitry Andric StreamString str_temp;
8549dba64beSDimitry Andric LLDB_LOGF(log,
8550b57cec5SDimitry Andric "[Debugger::FormatPrompt] I am into array || pointer && !range");
8560b57cec5SDimitry Andric
8570b57cec5SDimitry Andric if (target->HasSpecialPrintableRepresentation(val_obj_display,
8580b57cec5SDimitry Andric custom_format)) {
8590b57cec5SDimitry Andric // try to use the special cases
8600b57cec5SDimitry Andric bool success = target->DumpPrintableRepresentation(
8610b57cec5SDimitry Andric str_temp, val_obj_display, custom_format);
8629dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
8630b57cec5SDimitry Andric success ? "" : "n't");
8640b57cec5SDimitry Andric
8650b57cec5SDimitry Andric // should not happen
8660b57cec5SDimitry Andric if (success)
8670b57cec5SDimitry Andric s << str_temp.GetString();
8680b57cec5SDimitry Andric return true;
8690b57cec5SDimitry Andric } else {
8700b57cec5SDimitry Andric if (was_plain_var) // if ${var}
8710b57cec5SDimitry Andric {
8720b57cec5SDimitry Andric s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8730b57cec5SDimitry Andric } else if (is_pointer) // if pointer, value is the address stored
8740b57cec5SDimitry Andric {
8750b57cec5SDimitry Andric target->DumpPrintableRepresentation(
8760b57cec5SDimitry Andric s, val_obj_display, custom_format,
8770b57cec5SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eDisable);
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric return true;
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric
8830b57cec5SDimitry Andric // if directly trying to print ${var}, and this is an aggregate, display a
8840b57cec5SDimitry Andric // nice type @ location message
8850b57cec5SDimitry Andric if (is_aggregate && was_plain_var) {
8860b57cec5SDimitry Andric s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8870b57cec5SDimitry Andric return true;
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric // if directly trying to print ${var%V}, and this is an aggregate, do not let
8910b57cec5SDimitry Andric // the user do it
8920b57cec5SDimitry Andric if (is_aggregate &&
8930b57cec5SDimitry Andric ((was_var_format &&
8940b57cec5SDimitry Andric val_obj_display ==
8950b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue))) {
8960b57cec5SDimitry Andric s << "<invalid use of aggregate type>";
8970b57cec5SDimitry Andric return true;
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric
9000b57cec5SDimitry Andric if (!is_array_range) {
9019dba64beSDimitry Andric LLDB_LOGF(log,
9029dba64beSDimitry Andric "[Debugger::FormatPrompt] dumping ordinary printable output");
9030b57cec5SDimitry Andric return target->DumpPrintableRepresentation(s, val_obj_display,
9040b57cec5SDimitry Andric custom_format);
9050b57cec5SDimitry Andric } else {
9069dba64beSDimitry Andric LLDB_LOGF(log,
9079dba64beSDimitry Andric "[Debugger::FormatPrompt] checking if I can handle as array");
9080b57cec5SDimitry Andric if (!is_array && !is_pointer)
9090b57cec5SDimitry Andric return false;
9109dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
9110b57cec5SDimitry Andric StreamString special_directions_stream;
9120b57cec5SDimitry Andric llvm::StringRef special_directions;
9130b57cec5SDimitry Andric if (close_bracket_index != llvm::StringRef::npos &&
9140b57cec5SDimitry Andric subpath.size() > close_bracket_index) {
9150b57cec5SDimitry Andric ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
9160b57cec5SDimitry Andric special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
9170b57cec5SDimitry Andric additional_data.GetCString());
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric if (entry.fmt != eFormatDefault) {
9200b57cec5SDimitry Andric const char format_char =
9210b57cec5SDimitry Andric FormatManager::GetFormatAsFormatChar(entry.fmt);
9220b57cec5SDimitry Andric if (format_char != '\0')
9230b57cec5SDimitry Andric special_directions_stream.Printf("%%%c", format_char);
9240b57cec5SDimitry Andric else {
9250b57cec5SDimitry Andric const char *format_cstr =
9260b57cec5SDimitry Andric FormatManager::GetFormatAsCString(entry.fmt);
9270b57cec5SDimitry Andric special_directions_stream.Printf("%%%s", format_cstr);
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric } else if (entry.number != 0) {
9300b57cec5SDimitry Andric const char style_char = ConvertValueObjectStyleToChar(
9310b57cec5SDimitry Andric (ValueObject::ValueObjectRepresentationStyle)entry.number);
9320b57cec5SDimitry Andric if (style_char)
9330b57cec5SDimitry Andric special_directions_stream.Printf("%%%c", style_char);
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric special_directions_stream.PutChar('}');
9360b57cec5SDimitry Andric special_directions =
9370b57cec5SDimitry Andric llvm::StringRef(special_directions_stream.GetString());
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric
9400b57cec5SDimitry Andric // let us display items index_lower thru index_higher of this array
9410b57cec5SDimitry Andric s.PutChar('[');
9420b57cec5SDimitry Andric
9430b57cec5SDimitry Andric if (index_higher < 0)
9440b57cec5SDimitry Andric index_higher = valobj->GetNumChildren() - 1;
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric uint32_t max_num_children =
9470b57cec5SDimitry Andric target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
9480b57cec5SDimitry Andric
9490b57cec5SDimitry Andric bool success = true;
9500b57cec5SDimitry Andric for (int64_t index = index_lower; index <= index_higher; ++index) {
951*5f7ddb14SDimitry Andric ValueObject *item = ExpandIndexedExpression(target, index, false).get();
9520b57cec5SDimitry Andric
9530b57cec5SDimitry Andric if (!item) {
9549dba64beSDimitry Andric LLDB_LOGF(log,
9559dba64beSDimitry Andric "[Debugger::FormatPrompt] ERROR in getting child item at "
9560b57cec5SDimitry Andric "index %" PRId64,
9570b57cec5SDimitry Andric index);
9580b57cec5SDimitry Andric } else {
9599dba64beSDimitry Andric LLDB_LOGF(
9609dba64beSDimitry Andric log,
9610b57cec5SDimitry Andric "[Debugger::FormatPrompt] special_directions for child item: %s",
9620b57cec5SDimitry Andric special_directions.data() ? special_directions.data() : "");
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric
9650b57cec5SDimitry Andric if (special_directions.empty()) {
9660b57cec5SDimitry Andric success &= item->DumpPrintableRepresentation(s, val_obj_display,
9670b57cec5SDimitry Andric custom_format);
9680b57cec5SDimitry Andric } else {
9690b57cec5SDimitry Andric success &= FormatEntity::FormatStringRef(
9700b57cec5SDimitry Andric special_directions, s, sc, exe_ctx, nullptr, item, false, false);
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric
9730b57cec5SDimitry Andric if (--max_num_children == 0) {
9740b57cec5SDimitry Andric s.PutCString(", ...");
9750b57cec5SDimitry Andric break;
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric if (index < index_higher)
9790b57cec5SDimitry Andric s.PutChar(',');
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric s.PutChar(']');
9820b57cec5SDimitry Andric return success;
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric
DumpRegister(Stream & s,StackFrame * frame,const char * reg_name,Format format)9860b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
9870b57cec5SDimitry Andric Format format) {
9880b57cec5SDimitry Andric if (frame) {
9890b57cec5SDimitry Andric RegisterContext *reg_ctx = frame->GetRegisterContext().get();
9900b57cec5SDimitry Andric
9910b57cec5SDimitry Andric if (reg_ctx) {
9920b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
9930b57cec5SDimitry Andric if (reg_info) {
9940b57cec5SDimitry Andric RegisterValue reg_value;
9950b57cec5SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
9960b57cec5SDimitry Andric DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
9970b57cec5SDimitry Andric return true;
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric return false;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric
FormatThreadExtendedInfoRecurse(const FormatEntity::Entry & entry,const StructuredData::ObjectSP & thread_info_dictionary,const SymbolContext * sc,const ExecutionContext * exe_ctx,Stream & s)10050b57cec5SDimitry Andric static bool FormatThreadExtendedInfoRecurse(
10060b57cec5SDimitry Andric const FormatEntity::Entry &entry,
10070b57cec5SDimitry Andric const StructuredData::ObjectSP &thread_info_dictionary,
10080b57cec5SDimitry Andric const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
10090b57cec5SDimitry Andric llvm::StringRef path(entry.string);
10100b57cec5SDimitry Andric
10110b57cec5SDimitry Andric StructuredData::ObjectSP value =
10120b57cec5SDimitry Andric thread_info_dictionary->GetObjectForDotSeparatedPath(path);
10130b57cec5SDimitry Andric
10140b57cec5SDimitry Andric if (value) {
10150b57cec5SDimitry Andric if (value->GetType() == eStructuredDataTypeInteger) {
10160b57cec5SDimitry Andric const char *token_format = "0x%4.4" PRIx64;
10170b57cec5SDimitry Andric if (!entry.printf_format.empty())
10180b57cec5SDimitry Andric token_format = entry.printf_format.c_str();
10190b57cec5SDimitry Andric s.Printf(token_format, value->GetAsInteger()->GetValue());
10200b57cec5SDimitry Andric return true;
10210b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeFloat) {
10220b57cec5SDimitry Andric s.Printf("%f", value->GetAsFloat()->GetValue());
10230b57cec5SDimitry Andric return true;
10240b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeString) {
10250b57cec5SDimitry Andric s.Format("{0}", value->GetAsString()->GetValue());
10260b57cec5SDimitry Andric return true;
10270b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeArray) {
10280b57cec5SDimitry Andric if (value->GetAsArray()->GetSize() > 0) {
10290b57cec5SDimitry Andric s.Printf("%zu", value->GetAsArray()->GetSize());
10300b57cec5SDimitry Andric return true;
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeDictionary) {
10330b57cec5SDimitry Andric s.Printf("%zu",
10340b57cec5SDimitry Andric value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
10350b57cec5SDimitry Andric return true;
10360b57cec5SDimitry Andric }
10370b57cec5SDimitry Andric }
10380b57cec5SDimitry Andric
10390b57cec5SDimitry Andric return false;
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric
IsToken(const char * var_name_begin,const char * var)10420b57cec5SDimitry Andric static inline bool IsToken(const char *var_name_begin, const char *var) {
10430b57cec5SDimitry Andric return (::strncmp(var_name_begin, var, strlen(var)) == 0);
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry 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)10460b57cec5SDimitry Andric bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
10470b57cec5SDimitry Andric const SymbolContext *sc,
10480b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
10490b57cec5SDimitry Andric const Address *addr, ValueObject *valobj,
10500b57cec5SDimitry Andric bool function_changed,
10510b57cec5SDimitry Andric bool initial_function) {
10520b57cec5SDimitry Andric if (!format_str.empty()) {
10530b57cec5SDimitry Andric FormatEntity::Entry root;
10540b57cec5SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
10550b57cec5SDimitry Andric if (error.Success()) {
10560b57cec5SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
10570b57cec5SDimitry Andric function_changed, initial_function);
10580b57cec5SDimitry Andric }
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric return false;
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry 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)10630b57cec5SDimitry Andric bool FormatEntity::FormatCString(const char *format, Stream &s,
10640b57cec5SDimitry Andric const SymbolContext *sc,
10650b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
10660b57cec5SDimitry Andric const Address *addr, ValueObject *valobj,
10670b57cec5SDimitry Andric bool function_changed, bool initial_function) {
10680b57cec5SDimitry Andric if (format && format[0]) {
10690b57cec5SDimitry Andric FormatEntity::Entry root;
10700b57cec5SDimitry Andric llvm::StringRef format_str(format);
10710b57cec5SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
10720b57cec5SDimitry Andric if (error.Success()) {
10730b57cec5SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
10740b57cec5SDimitry Andric function_changed, initial_function);
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric }
10770b57cec5SDimitry Andric return false;
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric
Format(const Entry & entry,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)10800b57cec5SDimitry Andric bool FormatEntity::Format(const Entry &entry, Stream &s,
10810b57cec5SDimitry Andric const SymbolContext *sc,
10820b57cec5SDimitry Andric const ExecutionContext *exe_ctx, const Address *addr,
10830b57cec5SDimitry Andric ValueObject *valobj, bool function_changed,
10840b57cec5SDimitry Andric bool initial_function) {
10850b57cec5SDimitry Andric switch (entry.type) {
10860b57cec5SDimitry Andric case Entry::Type::Invalid:
10870b57cec5SDimitry Andric case Entry::Type::ParentNumber: // Only used for
10880b57cec5SDimitry Andric // FormatEntity::Entry::Definition encoding
10890b57cec5SDimitry Andric case Entry::Type::ParentString: // Only used for
10900b57cec5SDimitry Andric // FormatEntity::Entry::Definition encoding
10910b57cec5SDimitry Andric return false;
10920b57cec5SDimitry Andric case Entry::Type::EscapeCode:
10930b57cec5SDimitry Andric if (exe_ctx) {
10940b57cec5SDimitry Andric if (Target *target = exe_ctx->GetTargetPtr()) {
10950b57cec5SDimitry Andric Debugger &debugger = target->GetDebugger();
10960b57cec5SDimitry Andric if (debugger.GetUseColor()) {
10970b57cec5SDimitry Andric s.PutCString(entry.string);
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric // Always return true, so colors being disabled is transparent.
11020b57cec5SDimitry Andric return true;
11030b57cec5SDimitry Andric
11040b57cec5SDimitry Andric case Entry::Type::Root:
11050b57cec5SDimitry Andric for (const auto &child : entry.children) {
11060b57cec5SDimitry Andric if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
11070b57cec5SDimitry Andric initial_function)) {
11080b57cec5SDimitry Andric return false; // If any item of root fails, then the formatting fails
11090b57cec5SDimitry Andric }
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric return true; // Only return true if all items succeeded
11120b57cec5SDimitry Andric
11130b57cec5SDimitry Andric case Entry::Type::String:
11140b57cec5SDimitry Andric s.PutCString(entry.string);
11150b57cec5SDimitry Andric return true;
11160b57cec5SDimitry Andric
11170b57cec5SDimitry Andric case Entry::Type::Scope: {
11180b57cec5SDimitry Andric StreamString scope_stream;
11190b57cec5SDimitry Andric bool success = false;
11200b57cec5SDimitry Andric for (const auto &child : entry.children) {
11210b57cec5SDimitry Andric success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
11220b57cec5SDimitry Andric function_changed, initial_function);
11230b57cec5SDimitry Andric if (!success)
11240b57cec5SDimitry Andric break;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric // Only if all items in a scope succeed, then do we print the output into
11270b57cec5SDimitry Andric // the main stream
11280b57cec5SDimitry Andric if (success)
11290b57cec5SDimitry Andric s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
11300b57cec5SDimitry Andric }
11310b57cec5SDimitry Andric return true; // Scopes always successfully print themselves
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andric case Entry::Type::Variable:
11340b57cec5SDimitry Andric case Entry::Type::VariableSynthetic:
11350b57cec5SDimitry Andric case Entry::Type::ScriptVariable:
11360b57cec5SDimitry Andric case Entry::Type::ScriptVariableSynthetic:
11370b57cec5SDimitry Andric return DumpValue(s, sc, exe_ctx, entry, valobj);
11380b57cec5SDimitry Andric
11390b57cec5SDimitry Andric case Entry::Type::AddressFile:
11400b57cec5SDimitry Andric case Entry::Type::AddressLoad:
11410b57cec5SDimitry Andric case Entry::Type::AddressLoadOrFile:
1142480093f4SDimitry Andric return (
1143480093f4SDimitry Andric addr != nullptr && addr->IsValid() &&
1144480093f4SDimitry Andric DumpAddressAndContent(s, sc, exe_ctx, *addr,
11450b57cec5SDimitry Andric entry.type == Entry::Type::AddressLoadOrFile));
11460b57cec5SDimitry Andric
11470b57cec5SDimitry Andric case Entry::Type::ProcessID:
11480b57cec5SDimitry Andric if (exe_ctx) {
11490b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
11500b57cec5SDimitry Andric if (process) {
11510b57cec5SDimitry Andric const char *format = "%" PRIu64;
11520b57cec5SDimitry Andric if (!entry.printf_format.empty())
11530b57cec5SDimitry Andric format = entry.printf_format.c_str();
11540b57cec5SDimitry Andric s.Printf(format, process->GetID());
11550b57cec5SDimitry Andric return true;
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric }
11580b57cec5SDimitry Andric return false;
11590b57cec5SDimitry Andric
11600b57cec5SDimitry Andric case Entry::Type::ProcessFile:
11610b57cec5SDimitry Andric if (exe_ctx) {
11620b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
11630b57cec5SDimitry Andric if (process) {
11640b57cec5SDimitry Andric Module *exe_module = process->GetTarget().GetExecutableModulePointer();
11650b57cec5SDimitry Andric if (exe_module) {
11660b57cec5SDimitry Andric if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
11670b57cec5SDimitry Andric return true;
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric return false;
11720b57cec5SDimitry Andric
11730b57cec5SDimitry Andric case Entry::Type::ScriptProcess:
11740b57cec5SDimitry Andric if (exe_ctx) {
11750b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
11760b57cec5SDimitry Andric if (process)
11770b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, process,
11780b57cec5SDimitry Andric entry.string.c_str());
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric return false;
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric case Entry::Type::ThreadID:
11830b57cec5SDimitry Andric if (exe_ctx) {
11840b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
11850b57cec5SDimitry Andric if (thread) {
11860b57cec5SDimitry Andric const char *format = "0x%4.4" PRIx64;
11870b57cec5SDimitry Andric if (!entry.printf_format.empty()) {
11880b57cec5SDimitry Andric // Watch for the special "tid" format...
11890b57cec5SDimitry Andric if (entry.printf_format == "tid") {
11900b57cec5SDimitry Andric // TODO(zturner): Rather than hardcoding this to be platform
11910b57cec5SDimitry Andric // specific, it should be controlled by a setting and the default
11920b57cec5SDimitry Andric // value of the setting can be different depending on the platform.
11930b57cec5SDimitry Andric Target &target = thread->GetProcess()->GetTarget();
11940b57cec5SDimitry Andric ArchSpec arch(target.GetArchitecture());
11950b57cec5SDimitry Andric llvm::Triple::OSType ostype = arch.IsValid()
11960b57cec5SDimitry Andric ? arch.GetTriple().getOS()
11970b57cec5SDimitry Andric : llvm::Triple::UnknownOS;
11980b57cec5SDimitry Andric if ((ostype == llvm::Triple::FreeBSD) ||
11990b57cec5SDimitry Andric (ostype == llvm::Triple::Linux) ||
12000b57cec5SDimitry Andric (ostype == llvm::Triple::NetBSD)) {
12010b57cec5SDimitry Andric format = "%" PRIu64;
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric } else {
12040b57cec5SDimitry Andric format = entry.printf_format.c_str();
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric s.Printf(format, thread->GetID());
12080b57cec5SDimitry Andric return true;
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric return false;
12120b57cec5SDimitry Andric
12130b57cec5SDimitry Andric case Entry::Type::ThreadProtocolID:
12140b57cec5SDimitry Andric if (exe_ctx) {
12150b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12160b57cec5SDimitry Andric if (thread) {
12170b57cec5SDimitry Andric const char *format = "0x%4.4" PRIx64;
12180b57cec5SDimitry Andric if (!entry.printf_format.empty())
12190b57cec5SDimitry Andric format = entry.printf_format.c_str();
12200b57cec5SDimitry Andric s.Printf(format, thread->GetProtocolID());
12210b57cec5SDimitry Andric return true;
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric return false;
12250b57cec5SDimitry Andric
12260b57cec5SDimitry Andric case Entry::Type::ThreadIndexID:
12270b57cec5SDimitry Andric if (exe_ctx) {
12280b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12290b57cec5SDimitry Andric if (thread) {
12300b57cec5SDimitry Andric const char *format = "%" PRIu32;
12310b57cec5SDimitry Andric if (!entry.printf_format.empty())
12320b57cec5SDimitry Andric format = entry.printf_format.c_str();
12330b57cec5SDimitry Andric s.Printf(format, thread->GetIndexID());
12340b57cec5SDimitry Andric return true;
12350b57cec5SDimitry Andric }
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric return false;
12380b57cec5SDimitry Andric
12390b57cec5SDimitry Andric case Entry::Type::ThreadName:
12400b57cec5SDimitry Andric if (exe_ctx) {
12410b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12420b57cec5SDimitry Andric if (thread) {
12430b57cec5SDimitry Andric const char *cstr = thread->GetName();
12440b57cec5SDimitry Andric if (cstr && cstr[0]) {
12450b57cec5SDimitry Andric s.PutCString(cstr);
12460b57cec5SDimitry Andric return true;
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric }
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric return false;
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric case Entry::Type::ThreadQueue:
12530b57cec5SDimitry Andric if (exe_ctx) {
12540b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12550b57cec5SDimitry Andric if (thread) {
12560b57cec5SDimitry Andric const char *cstr = thread->GetQueueName();
12570b57cec5SDimitry Andric if (cstr && cstr[0]) {
12580b57cec5SDimitry Andric s.PutCString(cstr);
12590b57cec5SDimitry Andric return true;
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric }
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric return false;
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andric case Entry::Type::ThreadStopReason:
12660b57cec5SDimitry Andric if (exe_ctx) {
12675ffd83dbSDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
12685ffd83dbSDimitry Andric std::string stop_description = thread->GetStopDescription();
12695ffd83dbSDimitry Andric if (!stop_description.empty()) {
12705ffd83dbSDimitry Andric s.PutCString(stop_description);
12710b57cec5SDimitry Andric return true;
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric }
12755ffd83dbSDimitry Andric return false;
12765ffd83dbSDimitry Andric
12775ffd83dbSDimitry Andric case Entry::Type::ThreadStopReasonRaw:
12785ffd83dbSDimitry Andric if (exe_ctx) {
12795ffd83dbSDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
12805ffd83dbSDimitry Andric std::string stop_description = thread->GetStopDescriptionRaw();
12815ffd83dbSDimitry Andric if (!stop_description.empty()) {
12825ffd83dbSDimitry Andric s.PutCString(stop_description);
12835ffd83dbSDimitry Andric return true;
12845ffd83dbSDimitry Andric }
12855ffd83dbSDimitry Andric }
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric return false;
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric case Entry::Type::ThreadReturnValue:
12900b57cec5SDimitry Andric if (exe_ctx) {
12910b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12920b57cec5SDimitry Andric if (thread) {
12930b57cec5SDimitry Andric StopInfoSP stop_info_sp = thread->GetStopInfo();
12940b57cec5SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
12950b57cec5SDimitry Andric ValueObjectSP return_valobj_sp =
12960b57cec5SDimitry Andric StopInfo::GetReturnValueObject(stop_info_sp);
12970b57cec5SDimitry Andric if (return_valobj_sp) {
12980b57cec5SDimitry Andric return_valobj_sp->Dump(s);
12990b57cec5SDimitry Andric return true;
13000b57cec5SDimitry Andric }
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric }
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric return false;
13050b57cec5SDimitry Andric
13060b57cec5SDimitry Andric case Entry::Type::ThreadCompletedExpression:
13070b57cec5SDimitry Andric if (exe_ctx) {
13080b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13090b57cec5SDimitry Andric if (thread) {
13100b57cec5SDimitry Andric StopInfoSP stop_info_sp = thread->GetStopInfo();
13110b57cec5SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
13120b57cec5SDimitry Andric ExpressionVariableSP expression_var_sp =
13130b57cec5SDimitry Andric StopInfo::GetExpressionVariable(stop_info_sp);
13140b57cec5SDimitry Andric if (expression_var_sp && expression_var_sp->GetValueObject()) {
13150b57cec5SDimitry Andric expression_var_sp->GetValueObject()->Dump(s);
13160b57cec5SDimitry Andric return true;
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric return false;
13220b57cec5SDimitry Andric
13230b57cec5SDimitry Andric case Entry::Type::ScriptThread:
13240b57cec5SDimitry Andric if (exe_ctx) {
13250b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13260b57cec5SDimitry Andric if (thread)
13270b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
13280b57cec5SDimitry Andric entry.string.c_str());
13290b57cec5SDimitry Andric }
13300b57cec5SDimitry Andric return false;
13310b57cec5SDimitry Andric
13320b57cec5SDimitry Andric case Entry::Type::ThreadInfo:
13330b57cec5SDimitry Andric if (exe_ctx) {
13340b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13350b57cec5SDimitry Andric if (thread) {
13360b57cec5SDimitry Andric StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
13370b57cec5SDimitry Andric if (object_sp &&
13380b57cec5SDimitry Andric object_sp->GetType() == eStructuredDataTypeDictionary) {
13390b57cec5SDimitry Andric if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
13400b57cec5SDimitry Andric return true;
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric }
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric return false;
13450b57cec5SDimitry Andric
13460b57cec5SDimitry Andric case Entry::Type::TargetArch:
13470b57cec5SDimitry Andric if (exe_ctx) {
13480b57cec5SDimitry Andric Target *target = exe_ctx->GetTargetPtr();
13490b57cec5SDimitry Andric if (target) {
13500b57cec5SDimitry Andric const ArchSpec &arch = target->GetArchitecture();
13510b57cec5SDimitry Andric if (arch.IsValid()) {
13520b57cec5SDimitry Andric s.PutCString(arch.GetArchitectureName());
13530b57cec5SDimitry Andric return true;
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric }
13560b57cec5SDimitry Andric }
13570b57cec5SDimitry Andric return false;
13580b57cec5SDimitry Andric
13590b57cec5SDimitry Andric case Entry::Type::ScriptTarget:
13600b57cec5SDimitry Andric if (exe_ctx) {
13610b57cec5SDimitry Andric Target *target = exe_ctx->GetTargetPtr();
13620b57cec5SDimitry Andric if (target)
13630b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, target,
13640b57cec5SDimitry Andric entry.string.c_str());
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric return false;
13670b57cec5SDimitry Andric
13680b57cec5SDimitry Andric case Entry::Type::ModuleFile:
13690b57cec5SDimitry Andric if (sc) {
13700b57cec5SDimitry Andric Module *module = sc->module_sp.get();
13710b57cec5SDimitry Andric if (module) {
13720b57cec5SDimitry Andric if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
13730b57cec5SDimitry Andric return true;
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric return false;
13770b57cec5SDimitry Andric
13780b57cec5SDimitry Andric case Entry::Type::File:
13790b57cec5SDimitry Andric if (sc) {
13800b57cec5SDimitry Andric CompileUnit *cu = sc->comp_unit;
13810b57cec5SDimitry Andric if (cu) {
1382480093f4SDimitry Andric if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
13830b57cec5SDimitry Andric return true;
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric }
13860b57cec5SDimitry Andric return false;
13870b57cec5SDimitry Andric
13880b57cec5SDimitry Andric case Entry::Type::Lang:
13890b57cec5SDimitry Andric if (sc) {
13900b57cec5SDimitry Andric CompileUnit *cu = sc->comp_unit;
13910b57cec5SDimitry Andric if (cu) {
13920b57cec5SDimitry Andric const char *lang_name =
13930b57cec5SDimitry Andric Language::GetNameForLanguageType(cu->GetLanguage());
13940b57cec5SDimitry Andric if (lang_name) {
13950b57cec5SDimitry Andric s.PutCString(lang_name);
13960b57cec5SDimitry Andric return true;
13970b57cec5SDimitry Andric }
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric }
14000b57cec5SDimitry Andric return false;
14010b57cec5SDimitry Andric
14020b57cec5SDimitry Andric case Entry::Type::FrameIndex:
14030b57cec5SDimitry Andric if (exe_ctx) {
14040b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14050b57cec5SDimitry Andric if (frame) {
14060b57cec5SDimitry Andric const char *format = "%" PRIu32;
14070b57cec5SDimitry Andric if (!entry.printf_format.empty())
14080b57cec5SDimitry Andric format = entry.printf_format.c_str();
14090b57cec5SDimitry Andric s.Printf(format, frame->GetFrameIndex());
14100b57cec5SDimitry Andric return true;
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric return false;
14140b57cec5SDimitry Andric
14150b57cec5SDimitry Andric case Entry::Type::FrameRegisterPC:
14160b57cec5SDimitry Andric if (exe_ctx) {
14170b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14180b57cec5SDimitry Andric if (frame) {
14190b57cec5SDimitry Andric const Address &pc_addr = frame->GetFrameCodeAddress();
14200b57cec5SDimitry Andric if (pc_addr.IsValid()) {
1421480093f4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
14220b57cec5SDimitry Andric return true;
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric }
14260b57cec5SDimitry Andric return false;
14270b57cec5SDimitry Andric
14280b57cec5SDimitry Andric case Entry::Type::FrameRegisterSP:
14290b57cec5SDimitry Andric if (exe_ctx) {
14300b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14310b57cec5SDimitry Andric if (frame) {
14320b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
14330b57cec5SDimitry Andric (lldb::Format)entry.number))
14340b57cec5SDimitry Andric return true;
14350b57cec5SDimitry Andric }
14360b57cec5SDimitry Andric }
14370b57cec5SDimitry Andric return false;
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andric case Entry::Type::FrameRegisterFP:
14400b57cec5SDimitry Andric if (exe_ctx) {
14410b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14420b57cec5SDimitry Andric if (frame) {
14430b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
14440b57cec5SDimitry Andric (lldb::Format)entry.number))
14450b57cec5SDimitry Andric return true;
14460b57cec5SDimitry Andric }
14470b57cec5SDimitry Andric }
14480b57cec5SDimitry Andric return false;
14490b57cec5SDimitry Andric
14500b57cec5SDimitry Andric case Entry::Type::FrameRegisterFlags:
14510b57cec5SDimitry Andric if (exe_ctx) {
14520b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14530b57cec5SDimitry Andric if (frame) {
14540b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric,
14550b57cec5SDimitry Andric LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
14560b57cec5SDimitry Andric return true;
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric }
14590b57cec5SDimitry Andric return false;
14600b57cec5SDimitry Andric
14610b57cec5SDimitry Andric case Entry::Type::FrameNoDebug:
14620b57cec5SDimitry Andric if (exe_ctx) {
14630b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14640b57cec5SDimitry Andric if (frame) {
14650b57cec5SDimitry Andric return !frame->HasDebugInformation();
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric }
14680b57cec5SDimitry Andric return true;
14690b57cec5SDimitry Andric
14700b57cec5SDimitry Andric case Entry::Type::FrameRegisterByName:
14710b57cec5SDimitry Andric if (exe_ctx) {
14720b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14730b57cec5SDimitry Andric if (frame) {
14740b57cec5SDimitry Andric if (DumpRegister(s, frame, entry.string.c_str(),
14750b57cec5SDimitry Andric (lldb::Format)entry.number))
14760b57cec5SDimitry Andric return true;
14770b57cec5SDimitry Andric }
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric return false;
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric case Entry::Type::FrameIsArtificial: {
14820b57cec5SDimitry Andric if (exe_ctx)
14830b57cec5SDimitry Andric if (StackFrame *frame = exe_ctx->GetFramePtr())
14840b57cec5SDimitry Andric return frame->IsArtificial();
14850b57cec5SDimitry Andric return false;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric
14880b57cec5SDimitry Andric case Entry::Type::ScriptFrame:
14890b57cec5SDimitry Andric if (exe_ctx) {
14900b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14910b57cec5SDimitry Andric if (frame)
14920b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
14930b57cec5SDimitry Andric entry.string.c_str());
14940b57cec5SDimitry Andric }
14950b57cec5SDimitry Andric return false;
14960b57cec5SDimitry Andric
14970b57cec5SDimitry Andric case Entry::Type::FunctionID:
14980b57cec5SDimitry Andric if (sc) {
14990b57cec5SDimitry Andric if (sc->function) {
15000b57cec5SDimitry Andric s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
15010b57cec5SDimitry Andric return true;
15020b57cec5SDimitry Andric } else if (sc->symbol) {
15030b57cec5SDimitry Andric s.Printf("symbol[%u]", sc->symbol->GetID());
15040b57cec5SDimitry Andric return true;
15050b57cec5SDimitry Andric }
15060b57cec5SDimitry Andric }
15070b57cec5SDimitry Andric return false;
15080b57cec5SDimitry Andric
15090b57cec5SDimitry Andric case Entry::Type::FunctionDidChange:
15100b57cec5SDimitry Andric return function_changed;
15110b57cec5SDimitry Andric
15120b57cec5SDimitry Andric case Entry::Type::FunctionInitialFunction:
15130b57cec5SDimitry Andric return initial_function;
15140b57cec5SDimitry Andric
15150b57cec5SDimitry Andric case Entry::Type::FunctionName: {
1516*5f7ddb14SDimitry Andric if (!sc)
1517*5f7ddb14SDimitry Andric return false;
1518*5f7ddb14SDimitry Andric
15190b57cec5SDimitry Andric Language *language_plugin = nullptr;
15200b57cec5SDimitry Andric bool language_plugin_handled = false;
15210b57cec5SDimitry Andric StreamString ss;
1522*5f7ddb14SDimitry Andric
15230b57cec5SDimitry Andric if (sc->function)
15240b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
15250b57cec5SDimitry Andric else if (sc->symbol)
15260b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1527*5f7ddb14SDimitry Andric
1528*5f7ddb14SDimitry Andric if (language_plugin)
15290b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
15300b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1531*5f7ddb14SDimitry Andric
15320b57cec5SDimitry Andric if (language_plugin_handled) {
15330b57cec5SDimitry Andric s << ss.GetString();
15340b57cec5SDimitry Andric return true;
15350b57cec5SDimitry Andric } else {
15360b57cec5SDimitry Andric const char *name = nullptr;
15370b57cec5SDimitry Andric if (sc->function)
15380b57cec5SDimitry Andric name = sc->function->GetName().AsCString(nullptr);
15390b57cec5SDimitry Andric else if (sc->symbol)
15400b57cec5SDimitry Andric name = sc->symbol->GetName().AsCString(nullptr);
1541*5f7ddb14SDimitry Andric
15420b57cec5SDimitry Andric if (name) {
15430b57cec5SDimitry Andric s.PutCString(name);
15440b57cec5SDimitry Andric
15450b57cec5SDimitry Andric if (sc->block) {
15460b57cec5SDimitry Andric Block *inline_block = sc->block->GetContainingInlinedBlock();
15470b57cec5SDimitry Andric if (inline_block) {
15480b57cec5SDimitry Andric const InlineFunctionInfo *inline_info =
15490b57cec5SDimitry Andric sc->block->GetInlinedFunctionInfo();
15500b57cec5SDimitry Andric if (inline_info) {
15510b57cec5SDimitry Andric s.PutCString(" [inlined] ");
15525ffd83dbSDimitry Andric inline_info->GetName().Dump(&s);
15530b57cec5SDimitry Andric }
15540b57cec5SDimitry Andric }
15550b57cec5SDimitry Andric }
15560b57cec5SDimitry Andric return true;
15570b57cec5SDimitry Andric }
15580b57cec5SDimitry Andric }
15590b57cec5SDimitry Andric }
15600b57cec5SDimitry Andric return false;
15610b57cec5SDimitry Andric
15620b57cec5SDimitry Andric case Entry::Type::FunctionNameNoArgs: {
1563*5f7ddb14SDimitry Andric if (!sc)
1564*5f7ddb14SDimitry Andric return false;
1565*5f7ddb14SDimitry Andric
15660b57cec5SDimitry Andric Language *language_plugin = nullptr;
15670b57cec5SDimitry Andric bool language_plugin_handled = false;
15680b57cec5SDimitry Andric StreamString ss;
15690b57cec5SDimitry Andric if (sc->function)
15700b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
15710b57cec5SDimitry Andric else if (sc->symbol)
15720b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1573*5f7ddb14SDimitry Andric
1574*5f7ddb14SDimitry Andric if (language_plugin)
15750b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
15760b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
15770b57cec5SDimitry Andric ss);
1578*5f7ddb14SDimitry Andric
15790b57cec5SDimitry Andric if (language_plugin_handled) {
15800b57cec5SDimitry Andric s << ss.GetString();
15810b57cec5SDimitry Andric return true;
15820b57cec5SDimitry Andric } else {
15830b57cec5SDimitry Andric ConstString name;
15840b57cec5SDimitry Andric if (sc->function)
15850b57cec5SDimitry Andric name = sc->function->GetNameNoArguments();
15860b57cec5SDimitry Andric else if (sc->symbol)
15870b57cec5SDimitry Andric name = sc->symbol->GetNameNoArguments();
15880b57cec5SDimitry Andric if (name) {
15890b57cec5SDimitry Andric s.PutCString(name.GetCString());
15900b57cec5SDimitry Andric return true;
15910b57cec5SDimitry Andric }
15920b57cec5SDimitry Andric }
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric return false;
15950b57cec5SDimitry Andric
15960b57cec5SDimitry Andric case Entry::Type::FunctionNameWithArgs: {
1597*5f7ddb14SDimitry Andric if (!sc)
1598*5f7ddb14SDimitry Andric return false;
1599*5f7ddb14SDimitry Andric
16000b57cec5SDimitry Andric Language *language_plugin = nullptr;
16010b57cec5SDimitry Andric bool language_plugin_handled = false;
16020b57cec5SDimitry Andric StreamString ss;
16030b57cec5SDimitry Andric if (sc->function)
16040b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
16050b57cec5SDimitry Andric else if (sc->symbol)
16060b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1607*5f7ddb14SDimitry Andric
1608*5f7ddb14SDimitry Andric if (language_plugin)
16090b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
16100b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1611*5f7ddb14SDimitry Andric
16120b57cec5SDimitry Andric if (language_plugin_handled) {
16130b57cec5SDimitry Andric s << ss.GetString();
16140b57cec5SDimitry Andric return true;
16150b57cec5SDimitry Andric } else {
16160b57cec5SDimitry Andric // Print the function name with arguments in it
16170b57cec5SDimitry Andric if (sc->function) {
16180b57cec5SDimitry Andric ExecutionContextScope *exe_scope =
16190b57cec5SDimitry Andric exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
16200b57cec5SDimitry Andric const char *cstr = sc->function->GetName().AsCString(nullptr);
16210b57cec5SDimitry Andric if (cstr) {
16220b57cec5SDimitry Andric const InlineFunctionInfo *inline_info = nullptr;
16230b57cec5SDimitry Andric VariableListSP variable_list_sp;
16240b57cec5SDimitry Andric bool get_function_vars = true;
16250b57cec5SDimitry Andric if (sc->block) {
16260b57cec5SDimitry Andric Block *inline_block = sc->block->GetContainingInlinedBlock();
16270b57cec5SDimitry Andric
16280b57cec5SDimitry Andric if (inline_block) {
16290b57cec5SDimitry Andric get_function_vars = false;
16300b57cec5SDimitry Andric inline_info = sc->block->GetInlinedFunctionInfo();
16310b57cec5SDimitry Andric if (inline_info)
16320b57cec5SDimitry Andric variable_list_sp = inline_block->GetBlockVariableList(true);
16330b57cec5SDimitry Andric }
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric
16360b57cec5SDimitry Andric if (get_function_vars) {
16370b57cec5SDimitry Andric variable_list_sp =
16380b57cec5SDimitry Andric sc->function->GetBlock(true).GetBlockVariableList(true);
16390b57cec5SDimitry Andric }
16400b57cec5SDimitry Andric
16410b57cec5SDimitry Andric if (inline_info) {
16420b57cec5SDimitry Andric s.PutCString(cstr);
16430b57cec5SDimitry Andric s.PutCString(" [inlined] ");
16445ffd83dbSDimitry Andric cstr = inline_info->GetName().GetCString();
16450b57cec5SDimitry Andric }
16460b57cec5SDimitry Andric
16470b57cec5SDimitry Andric VariableList args;
16480b57cec5SDimitry Andric if (variable_list_sp)
16490b57cec5SDimitry Andric variable_list_sp->AppendVariablesWithScope(
16500b57cec5SDimitry Andric eValueTypeVariableArgument, args);
16510b57cec5SDimitry Andric if (args.GetSize() > 0) {
16520b57cec5SDimitry Andric const char *open_paren = strchr(cstr, '(');
16530b57cec5SDimitry Andric const char *close_paren = nullptr;
16540b57cec5SDimitry Andric const char *generic = strchr(cstr, '<');
16550b57cec5SDimitry Andric // if before the arguments list begins there is a template sign
16560b57cec5SDimitry Andric // then scan to the end of the generic args before you try to find
16570b57cec5SDimitry Andric // the arguments list
16580b57cec5SDimitry Andric if (generic && open_paren && generic < open_paren) {
16590b57cec5SDimitry Andric int generic_depth = 1;
16600b57cec5SDimitry Andric ++generic;
16610b57cec5SDimitry Andric for (; *generic && generic_depth > 0; generic++) {
16620b57cec5SDimitry Andric if (*generic == '<')
16630b57cec5SDimitry Andric generic_depth++;
16640b57cec5SDimitry Andric if (*generic == '>')
16650b57cec5SDimitry Andric generic_depth--;
16660b57cec5SDimitry Andric }
16670b57cec5SDimitry Andric if (*generic)
16680b57cec5SDimitry Andric open_paren = strchr(generic, '(');
16690b57cec5SDimitry Andric else
16700b57cec5SDimitry Andric open_paren = nullptr;
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric if (open_paren) {
16730b57cec5SDimitry Andric if (IsToken(open_paren, "(anonymous namespace)")) {
16740b57cec5SDimitry Andric open_paren =
16750b57cec5SDimitry Andric strchr(open_paren + strlen("(anonymous namespace)"), '(');
16760b57cec5SDimitry Andric if (open_paren)
16770b57cec5SDimitry Andric close_paren = strchr(open_paren, ')');
16780b57cec5SDimitry Andric } else
16790b57cec5SDimitry Andric close_paren = strchr(open_paren, ')');
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andric if (open_paren)
16830b57cec5SDimitry Andric s.Write(cstr, open_paren - cstr + 1);
16840b57cec5SDimitry Andric else {
16850b57cec5SDimitry Andric s.PutCString(cstr);
16860b57cec5SDimitry Andric s.PutChar('(');
16870b57cec5SDimitry Andric }
16880b57cec5SDimitry Andric const size_t num_args = args.GetSize();
16890b57cec5SDimitry Andric for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
16900b57cec5SDimitry Andric std::string buffer;
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andric VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
16930b57cec5SDimitry Andric ValueObjectSP var_value_sp(
16940b57cec5SDimitry Andric ValueObjectVariable::Create(exe_scope, var_sp));
16950b57cec5SDimitry Andric StreamString ss;
16960b57cec5SDimitry Andric llvm::StringRef var_representation;
16970b57cec5SDimitry Andric const char *var_name = var_value_sp->GetName().GetCString();
16980b57cec5SDimitry Andric if (var_value_sp->GetCompilerType().IsValid()) {
16990b57cec5SDimitry Andric if (var_value_sp && exe_scope->CalculateTarget())
17000b57cec5SDimitry Andric var_value_sp =
17010b57cec5SDimitry Andric var_value_sp->GetQualifiedRepresentationIfAvailable(
17020b57cec5SDimitry Andric exe_scope->CalculateTarget()
17030b57cec5SDimitry Andric ->TargetProperties::GetPreferDynamicValue(),
17040b57cec5SDimitry Andric exe_scope->CalculateTarget()
17050b57cec5SDimitry Andric ->TargetProperties::GetEnableSyntheticValue());
17060b57cec5SDimitry Andric if (var_value_sp->GetCompilerType().IsAggregateType() &&
17070b57cec5SDimitry Andric DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
17080b57cec5SDimitry Andric static StringSummaryFormat format(
17090b57cec5SDimitry Andric TypeSummaryImpl::Flags()
17100b57cec5SDimitry Andric .SetHideItemNames(false)
17110b57cec5SDimitry Andric .SetShowMembersOneLiner(true),
17120b57cec5SDimitry Andric "");
17130b57cec5SDimitry Andric format.FormatObject(var_value_sp.get(), buffer,
17140b57cec5SDimitry Andric TypeSummaryOptions());
17150b57cec5SDimitry Andric var_representation = buffer;
17160b57cec5SDimitry Andric } else
17170b57cec5SDimitry Andric var_value_sp->DumpPrintableRepresentation(
17180b57cec5SDimitry Andric ss,
17190b57cec5SDimitry Andric ValueObject::ValueObjectRepresentationStyle::
17200b57cec5SDimitry Andric eValueObjectRepresentationStyleSummary,
17210b57cec5SDimitry Andric eFormatDefault,
17220b57cec5SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eAllow,
17230b57cec5SDimitry Andric false);
17240b57cec5SDimitry Andric }
17250b57cec5SDimitry Andric
17260b57cec5SDimitry Andric if (!ss.GetString().empty())
17270b57cec5SDimitry Andric var_representation = ss.GetString();
17280b57cec5SDimitry Andric if (arg_idx > 0)
17290b57cec5SDimitry Andric s.PutCString(", ");
17300b57cec5SDimitry Andric if (var_value_sp->GetError().Success()) {
17310b57cec5SDimitry Andric if (!var_representation.empty())
17320b57cec5SDimitry Andric s.Printf("%s=%s", var_name, var_representation.str().c_str());
17330b57cec5SDimitry Andric else
17340b57cec5SDimitry Andric s.Printf("%s=%s at %s", var_name,
17350b57cec5SDimitry Andric var_value_sp->GetTypeName().GetCString(),
17360b57cec5SDimitry Andric var_value_sp->GetLocationAsCString());
17370b57cec5SDimitry Andric } else
17380b57cec5SDimitry Andric s.Printf("%s=<unavailable>", var_name);
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric
17410b57cec5SDimitry Andric if (close_paren)
17420b57cec5SDimitry Andric s.PutCString(close_paren);
17430b57cec5SDimitry Andric else
17440b57cec5SDimitry Andric s.PutChar(')');
17450b57cec5SDimitry Andric
17460b57cec5SDimitry Andric } else {
17470b57cec5SDimitry Andric s.PutCString(cstr);
17480b57cec5SDimitry Andric }
17490b57cec5SDimitry Andric return true;
17500b57cec5SDimitry Andric }
17510b57cec5SDimitry Andric } else if (sc->symbol) {
17520b57cec5SDimitry Andric const char *cstr = sc->symbol->GetName().AsCString(nullptr);
17530b57cec5SDimitry Andric if (cstr) {
17540b57cec5SDimitry Andric s.PutCString(cstr);
17550b57cec5SDimitry Andric return true;
17560b57cec5SDimitry Andric }
17570b57cec5SDimitry Andric }
17580b57cec5SDimitry Andric }
17590b57cec5SDimitry Andric }
17600b57cec5SDimitry Andric return false;
17610b57cec5SDimitry Andric
1762480093f4SDimitry Andric case Entry::Type::FunctionMangledName: {
1763*5f7ddb14SDimitry Andric if (!sc)
1764*5f7ddb14SDimitry Andric return false;
1765*5f7ddb14SDimitry Andric
1766480093f4SDimitry Andric const char *name = nullptr;
1767480093f4SDimitry Andric if (sc->symbol)
17685ffd83dbSDimitry Andric name =
17695ffd83dbSDimitry Andric sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
1770480093f4SDimitry Andric else if (sc->function)
1771480093f4SDimitry Andric name = sc->function->GetMangled()
17725ffd83dbSDimitry Andric .GetName(Mangled::ePreferMangled)
1773480093f4SDimitry Andric .AsCString();
1774480093f4SDimitry Andric
1775480093f4SDimitry Andric if (!name)
1776480093f4SDimitry Andric return false;
1777480093f4SDimitry Andric s.PutCString(name);
1778480093f4SDimitry Andric
1779*5f7ddb14SDimitry Andric if (sc->block && sc->block->GetContainingInlinedBlock()) {
1780480093f4SDimitry Andric if (const InlineFunctionInfo *inline_info =
1781480093f4SDimitry Andric sc->block->GetInlinedFunctionInfo()) {
1782480093f4SDimitry Andric s.PutCString(" [inlined] ");
17835ffd83dbSDimitry Andric inline_info->GetName().Dump(&s);
1784480093f4SDimitry Andric }
1785480093f4SDimitry Andric }
1786480093f4SDimitry Andric return true;
1787480093f4SDimitry Andric }
17880b57cec5SDimitry Andric case Entry::Type::FunctionAddrOffset:
17890b57cec5SDimitry Andric if (addr) {
17900b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
17910b57cec5SDimitry Andric false))
17920b57cec5SDimitry Andric return true;
17930b57cec5SDimitry Andric }
17940b57cec5SDimitry Andric return false;
17950b57cec5SDimitry Andric
17960b57cec5SDimitry Andric case Entry::Type::FunctionAddrOffsetConcrete:
17970b57cec5SDimitry Andric if (addr) {
17980b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
17990b57cec5SDimitry Andric true))
18000b57cec5SDimitry Andric return true;
18010b57cec5SDimitry Andric }
18020b57cec5SDimitry Andric return false;
18030b57cec5SDimitry Andric
18040b57cec5SDimitry Andric case Entry::Type::FunctionLineOffset:
1805*5f7ddb14SDimitry Andric if (sc)
1806*5f7ddb14SDimitry Andric return (DumpAddressOffsetFromFunction(
1807*5f7ddb14SDimitry Andric s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
1808*5f7ddb14SDimitry Andric false));
1809*5f7ddb14SDimitry Andric return false;
18100b57cec5SDimitry Andric
18110b57cec5SDimitry Andric case Entry::Type::FunctionPCOffset:
18120b57cec5SDimitry Andric if (exe_ctx) {
18130b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
18140b57cec5SDimitry Andric if (frame) {
18150b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
18160b57cec5SDimitry Andric frame->GetFrameCodeAddress(), false,
18170b57cec5SDimitry Andric false, false))
18180b57cec5SDimitry Andric return true;
18190b57cec5SDimitry Andric }
18200b57cec5SDimitry Andric }
18210b57cec5SDimitry Andric return false;
18220b57cec5SDimitry Andric
18230b57cec5SDimitry Andric case Entry::Type::FunctionChanged:
18240b57cec5SDimitry Andric return function_changed;
18250b57cec5SDimitry Andric
18260b57cec5SDimitry Andric case Entry::Type::FunctionIsOptimized: {
18270b57cec5SDimitry Andric bool is_optimized = false;
1828*5f7ddb14SDimitry Andric if (sc && sc->function && sc->function->GetIsOptimized()) {
18290b57cec5SDimitry Andric is_optimized = true;
18300b57cec5SDimitry Andric }
18310b57cec5SDimitry Andric return is_optimized;
18320b57cec5SDimitry Andric }
18330b57cec5SDimitry Andric
18340b57cec5SDimitry Andric case Entry::Type::FunctionInitial:
18350b57cec5SDimitry Andric return initial_function;
18360b57cec5SDimitry Andric
18370b57cec5SDimitry Andric case Entry::Type::LineEntryFile:
18380b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid()) {
18390b57cec5SDimitry Andric Module *module = sc->module_sp.get();
18400b57cec5SDimitry Andric if (module) {
18410b57cec5SDimitry Andric if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
18420b57cec5SDimitry Andric return true;
18430b57cec5SDimitry Andric }
18440b57cec5SDimitry Andric }
18450b57cec5SDimitry Andric return false;
18460b57cec5SDimitry Andric
18470b57cec5SDimitry Andric case Entry::Type::LineEntryLineNumber:
18480b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid()) {
18490b57cec5SDimitry Andric const char *format = "%" PRIu32;
18500b57cec5SDimitry Andric if (!entry.printf_format.empty())
18510b57cec5SDimitry Andric format = entry.printf_format.c_str();
18520b57cec5SDimitry Andric s.Printf(format, sc->line_entry.line);
18530b57cec5SDimitry Andric return true;
18540b57cec5SDimitry Andric }
18550b57cec5SDimitry Andric return false;
18560b57cec5SDimitry Andric
18570b57cec5SDimitry Andric case Entry::Type::LineEntryColumn:
18580b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
18590b57cec5SDimitry Andric const char *format = "%" PRIu32;
18600b57cec5SDimitry Andric if (!entry.printf_format.empty())
18610b57cec5SDimitry Andric format = entry.printf_format.c_str();
18620b57cec5SDimitry Andric s.Printf(format, sc->line_entry.column);
18630b57cec5SDimitry Andric return true;
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric return false;
18660b57cec5SDimitry Andric
18670b57cec5SDimitry Andric case Entry::Type::LineEntryStartAddress:
18680b57cec5SDimitry Andric case Entry::Type::LineEntryEndAddress:
18690b57cec5SDimitry Andric if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
18700b57cec5SDimitry Andric Address addr = sc->line_entry.range.GetBaseAddress();
18710b57cec5SDimitry Andric
18720b57cec5SDimitry Andric if (entry.type == Entry::Type::LineEntryEndAddress)
18730b57cec5SDimitry Andric addr.Slide(sc->line_entry.range.GetByteSize());
1874480093f4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
18750b57cec5SDimitry Andric return true;
18760b57cec5SDimitry Andric }
18770b57cec5SDimitry Andric return false;
18780b57cec5SDimitry Andric
18790b57cec5SDimitry Andric case Entry::Type::CurrentPCArrow:
18800b57cec5SDimitry Andric if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
18810b57cec5SDimitry Andric RegisterContextSP reg_ctx =
18820b57cec5SDimitry Andric exe_ctx->GetFramePtr()->GetRegisterContextSP();
18830b57cec5SDimitry Andric if (reg_ctx) {
18840b57cec5SDimitry Andric addr_t pc_loadaddr = reg_ctx->GetPC();
18850b57cec5SDimitry Andric if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
18860b57cec5SDimitry Andric Address pc;
18870b57cec5SDimitry Andric pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
18880b57cec5SDimitry Andric if (pc == *addr) {
18890b57cec5SDimitry Andric s.Printf("-> ");
18900b57cec5SDimitry Andric return true;
18910b57cec5SDimitry Andric }
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric }
18940b57cec5SDimitry Andric s.Printf(" ");
18950b57cec5SDimitry Andric return true;
18960b57cec5SDimitry Andric }
18970b57cec5SDimitry Andric return false;
18980b57cec5SDimitry Andric }
18990b57cec5SDimitry Andric return false;
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric
DumpCommaSeparatedChildEntryNames(Stream & s,const Definition * parent)1902*5f7ddb14SDimitry Andric static bool DumpCommaSeparatedChildEntryNames(Stream &s,
1903*5f7ddb14SDimitry Andric const Definition *parent) {
19040b57cec5SDimitry Andric if (parent->children) {
19050b57cec5SDimitry Andric const size_t n = parent->num_children;
19060b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
19070b57cec5SDimitry Andric if (i > 0)
19080b57cec5SDimitry Andric s.PutCString(", ");
19090b57cec5SDimitry Andric s.Printf("\"%s\"", parent->children[i].name);
19100b57cec5SDimitry Andric }
19110b57cec5SDimitry Andric return true;
19120b57cec5SDimitry Andric }
19130b57cec5SDimitry Andric return false;
19140b57cec5SDimitry Andric }
19150b57cec5SDimitry Andric
ParseEntry(const llvm::StringRef & format_str,const Definition * parent,FormatEntity::Entry & entry)19160b57cec5SDimitry Andric static Status ParseEntry(const llvm::StringRef &format_str,
1917*5f7ddb14SDimitry Andric const Definition *parent, FormatEntity::Entry &entry) {
19180b57cec5SDimitry Andric Status error;
19190b57cec5SDimitry Andric
19200b57cec5SDimitry Andric const size_t sep_pos = format_str.find_first_of(".[:");
19210b57cec5SDimitry Andric const char sep_char =
19220b57cec5SDimitry Andric (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
19230b57cec5SDimitry Andric llvm::StringRef key = format_str.substr(0, sep_pos);
19240b57cec5SDimitry Andric
19250b57cec5SDimitry Andric const size_t n = parent->num_children;
19260b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
1927*5f7ddb14SDimitry Andric const Definition *entry_def = parent->children + i;
19280b57cec5SDimitry Andric if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
19290b57cec5SDimitry Andric llvm::StringRef value;
19300b57cec5SDimitry Andric if (sep_char)
19310b57cec5SDimitry Andric value =
19320b57cec5SDimitry Andric format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
19330b57cec5SDimitry Andric switch (entry_def->type) {
19340b57cec5SDimitry Andric case FormatEntity::Entry::Type::ParentString:
19350b57cec5SDimitry Andric entry.string = format_str.str();
19360b57cec5SDimitry Andric return error; // Success
19370b57cec5SDimitry Andric
19380b57cec5SDimitry Andric case FormatEntity::Entry::Type::ParentNumber:
19390b57cec5SDimitry Andric entry.number = entry_def->data;
19400b57cec5SDimitry Andric return error; // Success
19410b57cec5SDimitry Andric
19420b57cec5SDimitry Andric case FormatEntity::Entry::Type::EscapeCode:
19430b57cec5SDimitry Andric entry.type = entry_def->type;
19440b57cec5SDimitry Andric entry.string = entry_def->string;
19450b57cec5SDimitry Andric return error; // Success
19460b57cec5SDimitry Andric
19470b57cec5SDimitry Andric default:
19480b57cec5SDimitry Andric entry.type = entry_def->type;
19490b57cec5SDimitry Andric break;
19500b57cec5SDimitry Andric }
19510b57cec5SDimitry Andric
19520b57cec5SDimitry Andric if (value.empty()) {
19530b57cec5SDimitry Andric if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
19540b57cec5SDimitry Andric if (entry_def->children) {
19550b57cec5SDimitry Andric StreamString error_strm;
19560b57cec5SDimitry Andric error_strm.Printf("'%s' can't be specified on its own, you must "
19570b57cec5SDimitry Andric "access one of its children: ",
19580b57cec5SDimitry Andric entry_def->name);
19590b57cec5SDimitry Andric DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
19600b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
19610b57cec5SDimitry Andric } else if (sep_char == ':') {
19620b57cec5SDimitry Andric // Any value whose separator is a with a ':' means this value has a
19630b57cec5SDimitry Andric // string argument that needs to be stored in the entry (like
19640b57cec5SDimitry Andric // "${script.var:}"). In this case the string value is the empty
19650b57cec5SDimitry Andric // string which is ok.
19660b57cec5SDimitry Andric } else {
19670b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", "invalid entry definitions");
19680b57cec5SDimitry Andric }
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric } else {
19710b57cec5SDimitry Andric if (entry_def->children) {
19720b57cec5SDimitry Andric error = ParseEntry(value, entry_def, entry);
19730b57cec5SDimitry Andric } else if (sep_char == ':') {
19740b57cec5SDimitry Andric // Any value whose separator is a with a ':' means this value has a
19750b57cec5SDimitry Andric // string argument that needs to be stored in the entry (like
19760b57cec5SDimitry Andric // "${script.var:modulename.function}")
19770b57cec5SDimitry Andric entry.string = value.str();
19780b57cec5SDimitry Andric } else {
19790b57cec5SDimitry Andric error.SetErrorStringWithFormat(
19800b57cec5SDimitry Andric "'%s' followed by '%s' but it has no children", key.str().c_str(),
19810b57cec5SDimitry Andric value.str().c_str());
19820b57cec5SDimitry Andric }
19830b57cec5SDimitry Andric }
19840b57cec5SDimitry Andric return error;
19850b57cec5SDimitry Andric }
19860b57cec5SDimitry Andric }
19870b57cec5SDimitry Andric StreamString error_strm;
19880b57cec5SDimitry Andric if (parent->type == FormatEntity::Entry::Type::Root)
19890b57cec5SDimitry Andric error_strm.Printf(
19900b57cec5SDimitry Andric "invalid top level item '%s'. Valid top level items are: ",
19910b57cec5SDimitry Andric key.str().c_str());
19920b57cec5SDimitry Andric else
19930b57cec5SDimitry Andric error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
19940b57cec5SDimitry Andric key.str().c_str(), parent->name);
19950b57cec5SDimitry Andric DumpCommaSeparatedChildEntryNames(error_strm, parent);
19960b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
19970b57cec5SDimitry Andric return error;
19980b57cec5SDimitry Andric }
19990b57cec5SDimitry Andric
FindEntry(const llvm::StringRef & format_str,const Definition * parent,llvm::StringRef & remainder)2000*5f7ddb14SDimitry Andric static const Definition *FindEntry(const llvm::StringRef &format_str,
2001*5f7ddb14SDimitry Andric const Definition *parent,
20020b57cec5SDimitry Andric llvm::StringRef &remainder) {
20030b57cec5SDimitry Andric Status error;
20040b57cec5SDimitry Andric
20050b57cec5SDimitry Andric std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
20060b57cec5SDimitry Andric const size_t n = parent->num_children;
20070b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
2008*5f7ddb14SDimitry Andric const Definition *entry_def = parent->children + i;
20090b57cec5SDimitry Andric if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
20100b57cec5SDimitry Andric if (p.second.empty()) {
20110b57cec5SDimitry Andric if (format_str.back() == '.')
20120b57cec5SDimitry Andric remainder = format_str.drop_front(format_str.size() - 1);
20130b57cec5SDimitry Andric else
20140b57cec5SDimitry Andric remainder = llvm::StringRef(); // Exact match
20150b57cec5SDimitry Andric return entry_def;
20160b57cec5SDimitry Andric } else {
20170b57cec5SDimitry Andric if (entry_def->children) {
20180b57cec5SDimitry Andric return FindEntry(p.second, entry_def, remainder);
20190b57cec5SDimitry Andric } else {
20200b57cec5SDimitry Andric remainder = p.second;
20210b57cec5SDimitry Andric return entry_def;
20220b57cec5SDimitry Andric }
20230b57cec5SDimitry Andric }
20240b57cec5SDimitry Andric }
20250b57cec5SDimitry Andric }
20260b57cec5SDimitry Andric remainder = format_str;
20270b57cec5SDimitry Andric return parent;
20280b57cec5SDimitry Andric }
20290b57cec5SDimitry Andric
ParseInternal(llvm::StringRef & format,Entry & parent_entry,uint32_t depth)20300b57cec5SDimitry Andric Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
20310b57cec5SDimitry Andric uint32_t depth) {
20320b57cec5SDimitry Andric Status error;
20330b57cec5SDimitry Andric while (!format.empty() && error.Success()) {
20340b57cec5SDimitry Andric const size_t non_special_chars = format.find_first_of("${}\\");
20350b57cec5SDimitry Andric
20360b57cec5SDimitry Andric if (non_special_chars == llvm::StringRef::npos) {
20370b57cec5SDimitry Andric // No special characters, just string bytes so add them and we are done
20380b57cec5SDimitry Andric parent_entry.AppendText(format);
20390b57cec5SDimitry Andric return error;
20400b57cec5SDimitry Andric }
20410b57cec5SDimitry Andric
20420b57cec5SDimitry Andric if (non_special_chars > 0) {
20430b57cec5SDimitry Andric // We have a special character, so add all characters before these as a
20440b57cec5SDimitry Andric // plain string
20450b57cec5SDimitry Andric parent_entry.AppendText(format.substr(0, non_special_chars));
20460b57cec5SDimitry Andric format = format.drop_front(non_special_chars);
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric
20490b57cec5SDimitry Andric switch (format[0]) {
20500b57cec5SDimitry Andric case '\0':
20510b57cec5SDimitry Andric return error;
20520b57cec5SDimitry Andric
20530b57cec5SDimitry Andric case '{': {
20540b57cec5SDimitry Andric format = format.drop_front(); // Skip the '{'
20550b57cec5SDimitry Andric Entry scope_entry(Entry::Type::Scope);
20560b57cec5SDimitry Andric error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
20570b57cec5SDimitry Andric if (error.Fail())
20580b57cec5SDimitry Andric return error;
20590b57cec5SDimitry Andric parent_entry.AppendEntry(std::move(scope_entry));
20600b57cec5SDimitry Andric } break;
20610b57cec5SDimitry Andric
20620b57cec5SDimitry Andric case '}':
20630b57cec5SDimitry Andric if (depth == 0)
20640b57cec5SDimitry Andric error.SetErrorString("unmatched '}' character");
20650b57cec5SDimitry Andric else
20660b57cec5SDimitry Andric format =
20670b57cec5SDimitry Andric format
20680b57cec5SDimitry Andric .drop_front(); // Skip the '}' as we are at the end of the scope
20690b57cec5SDimitry Andric return error;
20700b57cec5SDimitry Andric
20710b57cec5SDimitry Andric case '\\': {
20720b57cec5SDimitry Andric format = format.drop_front(); // Skip the '\' character
20730b57cec5SDimitry Andric if (format.empty()) {
20740b57cec5SDimitry Andric error.SetErrorString(
20750b57cec5SDimitry Andric "'\\' character was not followed by another character");
20760b57cec5SDimitry Andric return error;
20770b57cec5SDimitry Andric }
20780b57cec5SDimitry Andric
20790b57cec5SDimitry Andric const char desens_char = format[0];
20800b57cec5SDimitry Andric format = format.drop_front(); // Skip the desensitized char character
20810b57cec5SDimitry Andric switch (desens_char) {
20820b57cec5SDimitry Andric case 'a':
20830b57cec5SDimitry Andric parent_entry.AppendChar('\a');
20840b57cec5SDimitry Andric break;
20850b57cec5SDimitry Andric case 'b':
20860b57cec5SDimitry Andric parent_entry.AppendChar('\b');
20870b57cec5SDimitry Andric break;
20880b57cec5SDimitry Andric case 'f':
20890b57cec5SDimitry Andric parent_entry.AppendChar('\f');
20900b57cec5SDimitry Andric break;
20910b57cec5SDimitry Andric case 'n':
20920b57cec5SDimitry Andric parent_entry.AppendChar('\n');
20930b57cec5SDimitry Andric break;
20940b57cec5SDimitry Andric case 'r':
20950b57cec5SDimitry Andric parent_entry.AppendChar('\r');
20960b57cec5SDimitry Andric break;
20970b57cec5SDimitry Andric case 't':
20980b57cec5SDimitry Andric parent_entry.AppendChar('\t');
20990b57cec5SDimitry Andric break;
21000b57cec5SDimitry Andric case 'v':
21010b57cec5SDimitry Andric parent_entry.AppendChar('\v');
21020b57cec5SDimitry Andric break;
21030b57cec5SDimitry Andric case '\'':
21040b57cec5SDimitry Andric parent_entry.AppendChar('\'');
21050b57cec5SDimitry Andric break;
21060b57cec5SDimitry Andric case '\\':
21070b57cec5SDimitry Andric parent_entry.AppendChar('\\');
21080b57cec5SDimitry Andric break;
21090b57cec5SDimitry Andric case '0':
21100b57cec5SDimitry Andric // 1 to 3 octal chars
21110b57cec5SDimitry Andric {
21120b57cec5SDimitry Andric // Make a string that can hold onto the initial zero char, up to 3
21130b57cec5SDimitry Andric // octal digits, and a terminating NULL.
21140b57cec5SDimitry Andric char oct_str[5] = {0, 0, 0, 0, 0};
21150b57cec5SDimitry Andric
21160b57cec5SDimitry Andric int i;
21170b57cec5SDimitry Andric for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
21180b57cec5SDimitry Andric oct_str[i] = format[i];
21190b57cec5SDimitry Andric
21200b57cec5SDimitry Andric // We don't want to consume the last octal character since the main
21210b57cec5SDimitry Andric // for loop will do this for us, so we advance p by one less than i
21220b57cec5SDimitry Andric // (even if i is zero)
21230b57cec5SDimitry Andric format = format.drop_front(i);
21240b57cec5SDimitry Andric unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
21250b57cec5SDimitry Andric if (octal_value <= UINT8_MAX) {
21260b57cec5SDimitry Andric parent_entry.AppendChar((char)octal_value);
21270b57cec5SDimitry Andric } else {
21280b57cec5SDimitry Andric error.SetErrorString("octal number is larger than a single byte");
21290b57cec5SDimitry Andric return error;
21300b57cec5SDimitry Andric }
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric break;
21330b57cec5SDimitry Andric
21340b57cec5SDimitry Andric case 'x':
21350b57cec5SDimitry Andric // hex number in the format
21360b57cec5SDimitry Andric if (isxdigit(format[0])) {
21370b57cec5SDimitry Andric // Make a string that can hold onto two hex chars plus a
21380b57cec5SDimitry Andric // NULL terminator
21390b57cec5SDimitry Andric char hex_str[3] = {0, 0, 0};
21400b57cec5SDimitry Andric hex_str[0] = format[0];
21410b57cec5SDimitry Andric
21420b57cec5SDimitry Andric format = format.drop_front();
21430b57cec5SDimitry Andric
21440b57cec5SDimitry Andric if (isxdigit(format[0])) {
21450b57cec5SDimitry Andric hex_str[1] = format[0];
21460b57cec5SDimitry Andric format = format.drop_front();
21470b57cec5SDimitry Andric }
21480b57cec5SDimitry Andric
21490b57cec5SDimitry Andric unsigned long hex_value = strtoul(hex_str, nullptr, 16);
21500b57cec5SDimitry Andric if (hex_value <= UINT8_MAX) {
21510b57cec5SDimitry Andric parent_entry.AppendChar((char)hex_value);
21520b57cec5SDimitry Andric } else {
21530b57cec5SDimitry Andric error.SetErrorString("hex number is larger than a single byte");
21540b57cec5SDimitry Andric return error;
21550b57cec5SDimitry Andric }
21560b57cec5SDimitry Andric } else {
21570b57cec5SDimitry Andric parent_entry.AppendChar(desens_char);
21580b57cec5SDimitry Andric }
21590b57cec5SDimitry Andric break;
21600b57cec5SDimitry Andric
21610b57cec5SDimitry Andric default:
21620b57cec5SDimitry Andric // Just desensitize any other character by just printing what came
21630b57cec5SDimitry Andric // after the '\'
21640b57cec5SDimitry Andric parent_entry.AppendChar(desens_char);
21650b57cec5SDimitry Andric break;
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric } break;
21680b57cec5SDimitry Andric
21690b57cec5SDimitry Andric case '$':
21700b57cec5SDimitry Andric if (format.size() == 1) {
21710b57cec5SDimitry Andric // '$' at the end of a format string, just print the '$'
21720b57cec5SDimitry Andric parent_entry.AppendText("$");
21730b57cec5SDimitry Andric } else {
21740b57cec5SDimitry Andric format = format.drop_front(); // Skip the '$'
21750b57cec5SDimitry Andric
21760b57cec5SDimitry Andric if (format[0] == '{') {
21770b57cec5SDimitry Andric format = format.drop_front(); // Skip the '{'
21780b57cec5SDimitry Andric
21790b57cec5SDimitry Andric llvm::StringRef variable, variable_format;
21800b57cec5SDimitry Andric error = FormatEntity::ExtractVariableInfo(format, variable,
21810b57cec5SDimitry Andric variable_format);
21820b57cec5SDimitry Andric if (error.Fail())
21830b57cec5SDimitry Andric return error;
21840b57cec5SDimitry Andric bool verify_is_thread_id = false;
21850b57cec5SDimitry Andric Entry entry;
21860b57cec5SDimitry Andric if (!variable_format.empty()) {
21870b57cec5SDimitry Andric entry.printf_format = variable_format.str();
21880b57cec5SDimitry Andric
21890b57cec5SDimitry Andric // If the format contains a '%' we are going to assume this is a
21900b57cec5SDimitry Andric // printf style format. So if you want to format your thread ID
21910b57cec5SDimitry Andric // using "0x%llx" you can use: ${thread.id%0x%llx}
21920b57cec5SDimitry Andric //
21930b57cec5SDimitry Andric // If there is no '%' in the format, then it is assumed to be a
21940b57cec5SDimitry Andric // LLDB format name, or one of the extended formats specified in
21950b57cec5SDimitry Andric // the switch statement below.
21960b57cec5SDimitry Andric
21970b57cec5SDimitry Andric if (entry.printf_format.find('%') == std::string::npos) {
21980b57cec5SDimitry Andric bool clear_printf = false;
21990b57cec5SDimitry Andric
22000b57cec5SDimitry Andric if (FormatManager::GetFormatFromCString(
22010b57cec5SDimitry Andric entry.printf_format.c_str(), false, entry.fmt)) {
22020b57cec5SDimitry Andric // We have an LLDB format, so clear the printf format
22030b57cec5SDimitry Andric clear_printf = true;
22040b57cec5SDimitry Andric } else if (entry.printf_format.size() == 1) {
22050b57cec5SDimitry Andric switch (entry.printf_format[0]) {
22060b57cec5SDimitry Andric case '@': // if this is an @ sign, print ObjC description
22070b57cec5SDimitry Andric entry.number = ValueObject::
22080b57cec5SDimitry Andric eValueObjectRepresentationStyleLanguageSpecific;
22090b57cec5SDimitry Andric clear_printf = true;
22100b57cec5SDimitry Andric break;
22110b57cec5SDimitry Andric case 'V': // if this is a V, print the value using the default
22120b57cec5SDimitry Andric // format
22130b57cec5SDimitry Andric entry.number =
22140b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue;
22150b57cec5SDimitry Andric clear_printf = true;
22160b57cec5SDimitry Andric break;
22170b57cec5SDimitry Andric case 'L': // if this is an L, print the location of the value
22180b57cec5SDimitry Andric entry.number =
22190b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleLocation;
22200b57cec5SDimitry Andric clear_printf = true;
22210b57cec5SDimitry Andric break;
22220b57cec5SDimitry Andric case 'S': // if this is an S, print the summary after all
22230b57cec5SDimitry Andric entry.number =
22240b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
22250b57cec5SDimitry Andric clear_printf = true;
22260b57cec5SDimitry Andric break;
22270b57cec5SDimitry Andric case '#': // if this is a '#', print the number of children
22280b57cec5SDimitry Andric entry.number =
22290b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleChildrenCount;
22300b57cec5SDimitry Andric clear_printf = true;
22310b57cec5SDimitry Andric break;
22320b57cec5SDimitry Andric case 'T': // if this is a 'T', print the type
22330b57cec5SDimitry Andric entry.number =
22340b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleType;
22350b57cec5SDimitry Andric clear_printf = true;
22360b57cec5SDimitry Andric break;
22370b57cec5SDimitry Andric case 'N': // if this is a 'N', print the name
22380b57cec5SDimitry Andric entry.number =
22390b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleName;
22400b57cec5SDimitry Andric clear_printf = true;
22410b57cec5SDimitry Andric break;
22420b57cec5SDimitry Andric case '>': // if this is a '>', print the expression path
22430b57cec5SDimitry Andric entry.number = ValueObject::
22440b57cec5SDimitry Andric eValueObjectRepresentationStyleExpressionPath;
22450b57cec5SDimitry Andric clear_printf = true;
22460b57cec5SDimitry Andric break;
22470b57cec5SDimitry Andric default:
22480b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid format: '%s'",
22490b57cec5SDimitry Andric entry.printf_format.c_str());
22500b57cec5SDimitry Andric return error;
22510b57cec5SDimitry Andric }
22520b57cec5SDimitry Andric } else if (FormatManager::GetFormatFromCString(
22530b57cec5SDimitry Andric entry.printf_format.c_str(), true, entry.fmt)) {
22540b57cec5SDimitry Andric clear_printf = true;
22550b57cec5SDimitry Andric } else if (entry.printf_format == "tid") {
22560b57cec5SDimitry Andric verify_is_thread_id = true;
22570b57cec5SDimitry Andric } else {
22580b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid format: '%s'",
22590b57cec5SDimitry Andric entry.printf_format.c_str());
22600b57cec5SDimitry Andric return error;
22610b57cec5SDimitry Andric }
22620b57cec5SDimitry Andric
22630b57cec5SDimitry Andric // Our format string turned out to not be a printf style format
22640b57cec5SDimitry Andric // so lets clear the string
22650b57cec5SDimitry Andric if (clear_printf)
22660b57cec5SDimitry Andric entry.printf_format.clear();
22670b57cec5SDimitry Andric }
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric
22700b57cec5SDimitry Andric // Check for dereferences
22710b57cec5SDimitry Andric if (variable[0] == '*') {
22720b57cec5SDimitry Andric entry.deref = true;
22730b57cec5SDimitry Andric variable = variable.drop_front();
22740b57cec5SDimitry Andric }
22750b57cec5SDimitry Andric
22760b57cec5SDimitry Andric error = ParseEntry(variable, &g_root, entry);
22770b57cec5SDimitry Andric if (error.Fail())
22780b57cec5SDimitry Andric return error;
22790b57cec5SDimitry Andric
22800b57cec5SDimitry Andric if (verify_is_thread_id) {
22810b57cec5SDimitry Andric if (entry.type != Entry::Type::ThreadID &&
22820b57cec5SDimitry Andric entry.type != Entry::Type::ThreadProtocolID) {
22830b57cec5SDimitry Andric error.SetErrorString("the 'tid' format can only be used on "
22840b57cec5SDimitry Andric "${thread.id} and ${thread.protocol_id}");
22850b57cec5SDimitry Andric }
22860b57cec5SDimitry Andric }
22870b57cec5SDimitry Andric
22880b57cec5SDimitry Andric switch (entry.type) {
22890b57cec5SDimitry Andric case Entry::Type::Variable:
22900b57cec5SDimitry Andric case Entry::Type::VariableSynthetic:
22910b57cec5SDimitry Andric if (entry.number == 0) {
22920b57cec5SDimitry Andric if (entry.string.empty())
22930b57cec5SDimitry Andric entry.number =
22940b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue;
22950b57cec5SDimitry Andric else
22960b57cec5SDimitry Andric entry.number =
22970b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric break;
23000b57cec5SDimitry Andric default:
23010b57cec5SDimitry Andric // Make sure someone didn't try to dereference anything but ${var}
23020b57cec5SDimitry Andric // or ${svar}
23030b57cec5SDimitry Andric if (entry.deref) {
23040b57cec5SDimitry Andric error.SetErrorStringWithFormat(
23050b57cec5SDimitry Andric "${%s} can't be dereferenced, only ${var} and ${svar} can.",
23060b57cec5SDimitry Andric variable.str().c_str());
23070b57cec5SDimitry Andric return error;
23080b57cec5SDimitry Andric }
23090b57cec5SDimitry Andric }
23100b57cec5SDimitry Andric parent_entry.AppendEntry(std::move(entry));
23110b57cec5SDimitry Andric }
23120b57cec5SDimitry Andric }
23130b57cec5SDimitry Andric break;
23140b57cec5SDimitry Andric }
23150b57cec5SDimitry Andric }
23160b57cec5SDimitry Andric return error;
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric
ExtractVariableInfo(llvm::StringRef & format_str,llvm::StringRef & variable_name,llvm::StringRef & variable_format)23190b57cec5SDimitry Andric Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
23200b57cec5SDimitry Andric llvm::StringRef &variable_name,
23210b57cec5SDimitry Andric llvm::StringRef &variable_format) {
23220b57cec5SDimitry Andric Status error;
23230b57cec5SDimitry Andric variable_name = llvm::StringRef();
23240b57cec5SDimitry Andric variable_format = llvm::StringRef();
23250b57cec5SDimitry Andric
23260b57cec5SDimitry Andric const size_t paren_pos = format_str.find('}');
23270b57cec5SDimitry Andric if (paren_pos != llvm::StringRef::npos) {
23280b57cec5SDimitry Andric const size_t percent_pos = format_str.find('%');
23290b57cec5SDimitry Andric if (percent_pos < paren_pos) {
23300b57cec5SDimitry Andric if (percent_pos > 0) {
23310b57cec5SDimitry Andric if (percent_pos > 1)
23320b57cec5SDimitry Andric variable_name = format_str.substr(0, percent_pos);
23330b57cec5SDimitry Andric variable_format =
23340b57cec5SDimitry Andric format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
23350b57cec5SDimitry Andric }
23360b57cec5SDimitry Andric } else {
23370b57cec5SDimitry Andric variable_name = format_str.substr(0, paren_pos);
23380b57cec5SDimitry Andric }
23390b57cec5SDimitry Andric // Strip off elements and the formatting and the trailing '}'
23400b57cec5SDimitry Andric format_str = format_str.substr(paren_pos + 1);
23410b57cec5SDimitry Andric } else {
23420b57cec5SDimitry Andric error.SetErrorStringWithFormat(
23430b57cec5SDimitry Andric "missing terminating '}' character for '${%s'",
23440b57cec5SDimitry Andric format_str.str().c_str());
23450b57cec5SDimitry Andric }
23460b57cec5SDimitry Andric return error;
23470b57cec5SDimitry Andric }
23480b57cec5SDimitry Andric
FormatFileSpec(const FileSpec & file_spec,Stream & s,llvm::StringRef variable_name,llvm::StringRef variable_format)23490b57cec5SDimitry Andric bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
23500b57cec5SDimitry Andric llvm::StringRef variable_name,
23510b57cec5SDimitry Andric llvm::StringRef variable_format) {
23520b57cec5SDimitry Andric if (variable_name.empty() || variable_name.equals(".fullpath")) {
2353480093f4SDimitry Andric file_spec.Dump(s.AsRawOstream());
23540b57cec5SDimitry Andric return true;
23550b57cec5SDimitry Andric } else if (variable_name.equals(".basename")) {
23565ffd83dbSDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
23570b57cec5SDimitry Andric return true;
23580b57cec5SDimitry Andric } else if (variable_name.equals(".dirname")) {
23595ffd83dbSDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
23600b57cec5SDimitry Andric return true;
23610b57cec5SDimitry Andric }
23620b57cec5SDimitry Andric return false;
23630b57cec5SDimitry Andric }
23640b57cec5SDimitry Andric
MakeMatch(const llvm::StringRef & prefix,const char * suffix)23650b57cec5SDimitry Andric static std::string MakeMatch(const llvm::StringRef &prefix,
23660b57cec5SDimitry Andric const char *suffix) {
23670b57cec5SDimitry Andric std::string match(prefix.str());
23680b57cec5SDimitry Andric match.append(suffix);
23690b57cec5SDimitry Andric return match;
23700b57cec5SDimitry Andric }
23710b57cec5SDimitry Andric
AddMatches(const Definition * def,const llvm::StringRef & prefix,const llvm::StringRef & match_prefix,StringList & matches)2372*5f7ddb14SDimitry Andric static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
23730b57cec5SDimitry Andric const llvm::StringRef &match_prefix,
23740b57cec5SDimitry Andric StringList &matches) {
23750b57cec5SDimitry Andric const size_t n = def->num_children;
23760b57cec5SDimitry Andric if (n > 0) {
23770b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
23780b57cec5SDimitry Andric std::string match = prefix.str();
23790b57cec5SDimitry Andric if (match_prefix.empty())
23800b57cec5SDimitry Andric matches.AppendString(MakeMatch(prefix, def->children[i].name));
23810b57cec5SDimitry Andric else if (strncmp(def->children[i].name, match_prefix.data(),
23820b57cec5SDimitry Andric match_prefix.size()) == 0)
23830b57cec5SDimitry Andric matches.AppendString(
23840b57cec5SDimitry Andric MakeMatch(prefix, def->children[i].name + match_prefix.size()));
23850b57cec5SDimitry Andric }
23860b57cec5SDimitry Andric }
23870b57cec5SDimitry Andric }
23880b57cec5SDimitry Andric
AutoComplete(CompletionRequest & request)23899dba64beSDimitry Andric void FormatEntity::AutoComplete(CompletionRequest &request) {
23909dba64beSDimitry Andric llvm::StringRef str = request.GetCursorArgumentPrefix();
23910b57cec5SDimitry Andric
23920b57cec5SDimitry Andric const size_t dollar_pos = str.rfind('$');
23930b57cec5SDimitry Andric if (dollar_pos == llvm::StringRef::npos)
23949dba64beSDimitry Andric return;
23950b57cec5SDimitry Andric
23960b57cec5SDimitry Andric // Hitting TAB after $ at the end of the string add a "{"
23970b57cec5SDimitry Andric if (dollar_pos == str.size() - 1) {
23980b57cec5SDimitry Andric std::string match = str.str();
23990b57cec5SDimitry Andric match.append("{");
24000b57cec5SDimitry Andric request.AddCompletion(match);
24019dba64beSDimitry Andric return;
24020b57cec5SDimitry Andric }
24030b57cec5SDimitry Andric
24040b57cec5SDimitry Andric if (str[dollar_pos + 1] != '{')
24059dba64beSDimitry Andric return;
24060b57cec5SDimitry Andric
24070b57cec5SDimitry Andric const size_t close_pos = str.find('}', dollar_pos + 2);
24080b57cec5SDimitry Andric if (close_pos != llvm::StringRef::npos)
24099dba64beSDimitry Andric return;
24100b57cec5SDimitry Andric
24110b57cec5SDimitry Andric const size_t format_pos = str.find('%', dollar_pos + 2);
24120b57cec5SDimitry Andric if (format_pos != llvm::StringRef::npos)
24139dba64beSDimitry Andric return;
24140b57cec5SDimitry Andric
24150b57cec5SDimitry Andric llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
24160b57cec5SDimitry Andric if (partial_variable.empty()) {
24175ffd83dbSDimitry Andric // Suggest all top level entities as we are just past "${"
24180b57cec5SDimitry Andric StringList new_matches;
24190b57cec5SDimitry Andric AddMatches(&g_root, str, llvm::StringRef(), new_matches);
24200b57cec5SDimitry Andric request.AddCompletions(new_matches);
24219dba64beSDimitry Andric return;
24220b57cec5SDimitry Andric }
24230b57cec5SDimitry Andric
24240b57cec5SDimitry Andric // We have a partially specified variable, find it
24250b57cec5SDimitry Andric llvm::StringRef remainder;
2426*5f7ddb14SDimitry Andric const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
24270b57cec5SDimitry Andric if (!entry_def)
24289dba64beSDimitry Andric return;
24290b57cec5SDimitry Andric
24300b57cec5SDimitry Andric const size_t n = entry_def->num_children;
24310b57cec5SDimitry Andric
24320b57cec5SDimitry Andric if (remainder.empty()) {
24330b57cec5SDimitry Andric // Exact match
24340b57cec5SDimitry Andric if (n > 0) {
24350b57cec5SDimitry Andric // "${thread.info" <TAB>
24360b57cec5SDimitry Andric request.AddCompletion(MakeMatch(str, "."));
24370b57cec5SDimitry Andric } else {
24380b57cec5SDimitry Andric // "${thread.id" <TAB>
24390b57cec5SDimitry Andric request.AddCompletion(MakeMatch(str, "}"));
24400b57cec5SDimitry Andric }
24410b57cec5SDimitry Andric } else if (remainder.equals(".")) {
24420b57cec5SDimitry Andric // "${thread." <TAB>
24430b57cec5SDimitry Andric StringList new_matches;
24440b57cec5SDimitry Andric AddMatches(entry_def, str, llvm::StringRef(), new_matches);
24450b57cec5SDimitry Andric request.AddCompletions(new_matches);
24460b57cec5SDimitry Andric } else {
24470b57cec5SDimitry Andric // We have a partial match
24480b57cec5SDimitry Andric // "${thre" <TAB>
24490b57cec5SDimitry Andric StringList new_matches;
24500b57cec5SDimitry Andric AddMatches(entry_def, str, remainder, new_matches);
24510b57cec5SDimitry Andric request.AddCompletions(new_matches);
24520b57cec5SDimitry Andric }
24530b57cec5SDimitry Andric }
2454