1554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===// 2554f68d3SGreg Clayton // 3554f68d3SGreg Clayton // The LLVM Compiler Infrastructure 4554f68d3SGreg Clayton // 5554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source 6554f68d3SGreg Clayton // License. See LICENSE.TXT for details. 7554f68d3SGreg Clayton // 8554f68d3SGreg Clayton //===----------------------------------------------------------------------===// 9554f68d3SGreg Clayton 10554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 11554f68d3SGreg Clayton 12554f68d3SGreg Clayton #include "lldb/Core/Address.h" 13*2f3df613SZachary Turner #include "lldb/Core/AddressRange.h" // for AddressRange 14*2f3df613SZachary Turner #include "lldb/Core/ArchSpec.h" // for ArchSpec 15554f68d3SGreg Clayton #include "lldb/Core/Debugger.h" 16554f68d3SGreg Clayton #include "lldb/Core/Module.h" 17*2f3df613SZachary Turner #include "lldb/Core/RegisterValue.h" // for RegisterValue 18*2f3df613SZachary Turner #include "lldb/Core/StructuredData.h" // for StructuredData::O... 19554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h" 20554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 21554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h" 22*2f3df613SZachary Turner #include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier... 23554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h" 24*2f3df613SZachary Turner #include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::... 25937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h" 26554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 27554f68d3SGreg Clayton #include "lldb/Symbol/Block.h" 28554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 29*2f3df613SZachary Turner #include "lldb/Symbol/CompilerType.h" // for CompilerType 30554f68d3SGreg Clayton #include "lldb/Symbol/Function.h" 31554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h" 32554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h" 33*2f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext 34554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h" 35554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h" 36*2f3df613SZachary Turner #include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS... 370e0984eeSJim Ingham #include "lldb/Target/Language.h" 38554f68d3SGreg Clayton #include "lldb/Target/Process.h" 39554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h" 40554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h" 41554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h" 42554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h" 43554f68d3SGreg Clayton #include "lldb/Target/Target.h" 44554f68d3SGreg Clayton #include "lldb/Target/Thread.h" 45554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 46*2f3df613SZachary Turner #include "lldb/Utility/ConstString.h" // for ConstString, oper... 475713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 48*2f3df613SZachary Turner #include "lldb/Utility/Log.h" // for Log 49*2f3df613SZachary Turner #include "lldb/Utility/Logging.h" // for GetLogIfAllCatego... 50*2f3df613SZachary Turner #include "lldb/Utility/SharingPtr.h" // for SharingPtr 51bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 52bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 53*2f3df613SZachary Turner #include "lldb/Utility/StringList.h" // for StringList 54*2f3df613SZachary Turner #include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS 55*2f3df613SZachary Turner #include "lldb/lldb-forward.h" // for ValueObjectSP 56*2f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" 57*2f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 58*2f3df613SZachary Turner #include "llvm/ADT/Triple.h" // for Triple, Triple::O... 59*2f3df613SZachary Turner #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH 60*2f3df613SZachary Turner 61*2f3df613SZachary Turner #include <ctype.h> // for isxdigit 62*2f3df613SZachary Turner #include <inttypes.h> // for PRIu64, PRIx64 63*2f3df613SZachary Turner #include <memory> // for shared_ptr, opera... 64*2f3df613SZachary Turner #include <stdio.h> // for sprintf 65*2f3df613SZachary Turner #include <stdlib.h> // for strtoul 66*2f3df613SZachary Turner #include <string.h> // for size_t, strchr 67*2f3df613SZachary Turner #include <type_traits> // for move 68*2f3df613SZachary Turner #include <utility> // for pair 69*2f3df613SZachary Turner 70*2f3df613SZachary Turner namespace lldb_private { 71*2f3df613SZachary Turner class ScriptInterpreter; 72*2f3df613SZachary Turner } 73*2f3df613SZachary Turner namespace lldb_private { 74*2f3df613SZachary Turner struct RegisterInfo; 75*2f3df613SZachary Turner } 76554f68d3SGreg Clayton 77554f68d3SGreg Clayton using namespace lldb; 78554f68d3SGreg Clayton using namespace lldb_private; 79554f68d3SGreg Clayton 80b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath }; 81554f68d3SGreg Clayton 82b9c1b51eSKate Stone #define ENTRY(n, t, f) \ 83b9c1b51eSKate Stone { \ 84b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 85b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false \ 86b9c1b51eSKate Stone } 87b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v) \ 88b9c1b51eSKate Stone { \ 89b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 90b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, v, 0, nullptr, false \ 91b9c1b51eSKate Stone } 92b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c) \ 93b9c1b51eSKate Stone { \ 94b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 95e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 96e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \ 97b9c1b51eSKate Stone } 98b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \ 99b9c1b51eSKate Stone { \ 100b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 101e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 102e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, true \ 103b9c1b51eSKate Stone } 104b9c1b51eSKate Stone #define ENTRY_STRING(n, s) \ 105b9c1b51eSKate Stone { \ 106b9c1b51eSKate Stone n, s, FormatEntity::Entry::Type::InsertString, \ 107b9c1b51eSKate Stone FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false \ 108b9c1b51eSKate Stone } 109b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = { 110b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 111554f68d3SGreg Clayton 112b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = { 113b9c1b51eSKate Stone ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64), 114554f68d3SGreg Clayton ENTRY("load", AddressLoadOrFile, UInt64), 115554f68d3SGreg Clayton }; 116554f68d3SGreg Clayton 117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = { 118554f68d3SGreg Clayton ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), 119554f68d3SGreg Clayton ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), 120b9c1b51eSKate Stone ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)}; 121554f68d3SGreg Clayton 122b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = { 123554f68d3SGreg Clayton ENTRY("index", FrameIndex, UInt32), 124554f68d3SGreg Clayton ENTRY("pc", FrameRegisterPC, UInt64), 125554f68d3SGreg Clayton ENTRY("fp", FrameRegisterFP, UInt64), 126554f68d3SGreg Clayton ENTRY("sp", FrameRegisterSP, UInt64), 127554f68d3SGreg Clayton ENTRY("flags", FrameRegisterFlags, UInt64), 1286a9767c7SJim Ingham ENTRY("no-debug", FrameNoDebug, None), 129554f68d3SGreg Clayton ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), 130554f68d3SGreg Clayton }; 131554f68d3SGreg Clayton 132b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = { 133b9c1b51eSKate Stone ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString), 134554f68d3SGreg Clayton ENTRY("name-without-args", FunctionNameNoArgs, CString), 135554f68d3SGreg Clayton ENTRY("name-with-args", FunctionNameWithArgs, CString), 136554f68d3SGreg Clayton ENTRY("addr-offset", FunctionAddrOffset, UInt64), 137b9c1b51eSKate Stone ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, 138b9c1b51eSKate Stone UInt64), 139554f68d3SGreg Clayton ENTRY("line-offset", FunctionLineOffset, UInt64), 140c980fa92SJason Molenda ENTRY("pc-offset", FunctionPCOffset, UInt64), 141c980fa92SJason Molenda ENTRY("initial-function", FunctionInitial, None), 1426ab659a9SJason Molenda ENTRY("changed", FunctionChanged, None), 143b9c1b51eSKate Stone ENTRY("is-optimized", FunctionIsOptimized, None)}; 144554f68d3SGreg Clayton 145b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = { 146554f68d3SGreg Clayton ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), 147554f68d3SGreg Clayton ENTRY("number", LineEntryLineNumber, UInt32), 148554f68d3SGreg Clayton ENTRY("start-addr", LineEntryStartAddress, UInt64), 149554f68d3SGreg Clayton ENTRY("end-addr", LineEntryEndAddress, UInt64), 150554f68d3SGreg Clayton }; 151554f68d3SGreg Clayton 152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = { 153554f68d3SGreg Clayton ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), 154554f68d3SGreg Clayton }; 155554f68d3SGreg Clayton 156b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = { 157554f68d3SGreg Clayton ENTRY("id", ProcessID, UInt64), 158554f68d3SGreg Clayton ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename), 159554f68d3SGreg Clayton ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries), 160554f68d3SGreg Clayton }; 161554f68d3SGreg Clayton 162b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = { 163b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 164554f68d3SGreg Clayton 165b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = { 166b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 167554f68d3SGreg Clayton 168b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = { 169554f68d3SGreg Clayton ENTRY("id", ThreadID, UInt64), 170554f68d3SGreg Clayton ENTRY("protocol_id", ThreadProtocolID, UInt64), 171554f68d3SGreg Clayton ENTRY("index", ThreadIndexID, UInt32), 172554f68d3SGreg Clayton ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry), 173554f68d3SGreg Clayton ENTRY("queue", ThreadQueue, CString), 174554f68d3SGreg Clayton ENTRY("name", ThreadName, CString), 175554f68d3SGreg Clayton ENTRY("stop-reason", ThreadStopReason, CString), 176554f68d3SGreg Clayton ENTRY("return-value", ThreadReturnValue, CString), 177554f68d3SGreg Clayton ENTRY("completed-expression", ThreadCompletedExpression, CString), 178554f68d3SGreg Clayton }; 179554f68d3SGreg Clayton 180b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = { 181554f68d3SGreg Clayton ENTRY("arch", TargetArch, CString), 182554f68d3SGreg Clayton }; 183554f68d3SGreg Clayton 184554f68d3SGreg Clayton #define _TO_STR2(_val) #_val 185554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val) 186554f68d3SGreg Clayton 187b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { 188b9c1b51eSKate Stone ENTRY_STRING("black", 189b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 190554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 191b9c1b51eSKate Stone ENTRY_STRING("green", 192b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 193b9c1b51eSKate Stone ENTRY_STRING("yellow", 194b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 195b9c1b51eSKate Stone ENTRY_STRING("blue", 196b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 197b9c1b51eSKate Stone ENTRY_STRING("purple", 198b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 199b9c1b51eSKate Stone ENTRY_STRING("cyan", 200b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 201b9c1b51eSKate Stone ENTRY_STRING("white", 202b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 203554f68d3SGreg Clayton }; 204554f68d3SGreg Clayton 205b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { 206b9c1b51eSKate Stone ENTRY_STRING("black", 207b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 208554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 209b9c1b51eSKate Stone ENTRY_STRING("green", 210b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 211b9c1b51eSKate Stone ENTRY_STRING("yellow", 212b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 213b9c1b51eSKate Stone ENTRY_STRING("blue", 214b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 215b9c1b51eSKate Stone ENTRY_STRING("purple", 216b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 217b9c1b51eSKate Stone ENTRY_STRING("cyan", 218b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 219b9c1b51eSKate Stone ENTRY_STRING("white", 220b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 221554f68d3SGreg Clayton }; 222554f68d3SGreg Clayton 223b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = { 224554f68d3SGreg Clayton ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries), 225554f68d3SGreg Clayton ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries), 226b9c1b51eSKate Stone ENTRY_STRING("normal", 227b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 228554f68d3SGreg Clayton ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 229554f68d3SGreg Clayton ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 230b9c1b51eSKate Stone ENTRY_STRING("italic", 231b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 232b9c1b51eSKate Stone ENTRY_STRING("underline", 233b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 234b9c1b51eSKate Stone ENTRY_STRING("slow-blink", 235b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 236b9c1b51eSKate Stone ENTRY_STRING("fast-blink", 237b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 238b9c1b51eSKate Stone ENTRY_STRING("negative", 239b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 240b9c1b51eSKate Stone ENTRY_STRING("conceal", 241b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 242b9c1b51eSKate Stone ENTRY_STRING("crossed-out", 243b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 244554f68d3SGreg Clayton }; 245554f68d3SGreg Clayton 246b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = { 247554f68d3SGreg Clayton ENTRY("frame", ScriptFrame, None), 248554f68d3SGreg Clayton ENTRY("process", ScriptProcess, None), 249554f68d3SGreg Clayton ENTRY("target", ScriptTarget, None), 250554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 251554f68d3SGreg Clayton ENTRY("var", ScriptVariable, None), 252554f68d3SGreg Clayton ENTRY("svar", ScriptVariableSynthetic, None), 253554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 254554f68d3SGreg Clayton }; 255554f68d3SGreg Clayton 256b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = { 257554f68d3SGreg Clayton ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries), 258554f68d3SGreg Clayton ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64), 259554f68d3SGreg Clayton ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries), 260554f68d3SGreg Clayton ENTRY("current-pc-arrow", CurrentPCArrow, CString), 261554f68d3SGreg Clayton ENTRY_CHILDREN("file", File, CString, g_file_child_entries), 262dc975670SDawn Perchik ENTRY("language", Lang, CString), 263554f68d3SGreg Clayton ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries), 264554f68d3SGreg Clayton ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries), 265554f68d3SGreg Clayton ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries), 266554f68d3SGreg Clayton ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries), 267554f68d3SGreg Clayton ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries), 268554f68d3SGreg Clayton ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries), 269b9c1b51eSKate Stone ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None, 270b9c1b51eSKate Stone g_svar_child_entries), 271554f68d3SGreg Clayton ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries), 272554f68d3SGreg Clayton ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries), 273554f68d3SGreg Clayton ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries), 274554f68d3SGreg Clayton }; 275554f68d3SGreg Clayton 276b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root = 277b9c1b51eSKate Stone ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries); 278554f68d3SGreg Clayton 279b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s) 280b9c1b51eSKate Stone : string(s.data(), s.size()), printf_format(), children(), 281b9c1b51eSKate Stone definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), 282b9c1b51eSKate Stone number(0), deref(false) {} 283554f68d3SGreg Clayton 284b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch) 285b9c1b51eSKate Stone : string(1, ch), printf_format(), children(), definition(nullptr), 286b9c1b51eSKate Stone type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} 287554f68d3SGreg Clayton 288b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) { 289554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 290554f68d3SGreg Clayton children.push_back(Entry(ch)); 291554f68d3SGreg Clayton else 292554f68d3SGreg Clayton children.back().string.append(1, ch); 293554f68d3SGreg Clayton } 294554f68d3SGreg Clayton 295b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { 296554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 297554f68d3SGreg Clayton children.push_back(Entry(s)); 298554f68d3SGreg Clayton else 299554f68d3SGreg Clayton children.back().string.append(s.data(), s.size()); 300554f68d3SGreg Clayton } 301554f68d3SGreg Clayton 302b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) { 303554f68d3SGreg Clayton return AppendText(llvm::StringRef(cstr)); 304554f68d3SGreg Clayton } 305554f68d3SGreg Clayton 306b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { 307554f68d3SGreg Clayton entry.Clear(); 308554f68d3SGreg Clayton entry.type = Entry::Type::Root; 309554f68d3SGreg Clayton llvm::StringRef modifiable_format(format_str); 310554f68d3SGreg Clayton return ParseInternal(modifiable_format, entry, 0); 311554f68d3SGreg Clayton } 312554f68d3SGreg Clayton 313b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee) \ 314b9c1b51eSKate Stone case FormatEntity::Entry::Type::eee: \ 315b9c1b51eSKate Stone return #eee 316554f68d3SGreg Clayton 317b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) { 318b9c1b51eSKate Stone switch (t) { 319554f68d3SGreg Clayton ENUM_TO_CSTR(Invalid); 320554f68d3SGreg Clayton ENUM_TO_CSTR(ParentNumber); 321554f68d3SGreg Clayton ENUM_TO_CSTR(ParentString); 322554f68d3SGreg Clayton ENUM_TO_CSTR(InsertString); 323554f68d3SGreg Clayton ENUM_TO_CSTR(Root); 324554f68d3SGreg Clayton ENUM_TO_CSTR(String); 325554f68d3SGreg Clayton ENUM_TO_CSTR(Scope); 326554f68d3SGreg Clayton ENUM_TO_CSTR(Variable); 327554f68d3SGreg Clayton ENUM_TO_CSTR(VariableSynthetic); 328554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariable); 329554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariableSynthetic); 330554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoad); 331554f68d3SGreg Clayton ENUM_TO_CSTR(AddressFile); 332554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoadOrFile); 333554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessID); 334554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessFile); 335554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptProcess); 336554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadID); 337554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadProtocolID); 338554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadIndexID); 339554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadName); 340554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadQueue); 341554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadStopReason); 342554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadReturnValue); 343554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadCompletedExpression); 344554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptThread); 345554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadInfo); 346554f68d3SGreg Clayton ENUM_TO_CSTR(TargetArch); 347554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptTarget); 348554f68d3SGreg Clayton ENUM_TO_CSTR(ModuleFile); 349554f68d3SGreg Clayton ENUM_TO_CSTR(File); 350dc975670SDawn Perchik ENUM_TO_CSTR(Lang); 351554f68d3SGreg Clayton ENUM_TO_CSTR(FrameIndex); 3526a9767c7SJim Ingham ENUM_TO_CSTR(FrameNoDebug); 353554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterPC); 354554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterSP); 355554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFP); 356554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFlags); 357554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterByName); 358554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptFrame); 359554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionID); 360554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionDidChange); 361554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionInitialFunction); 362554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionName); 363554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameWithArgs); 364554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameNoArgs); 365554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffset); 366554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 367554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionLineOffset); 368554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionPCOffset); 369c980fa92SJason Molenda ENUM_TO_CSTR(FunctionInitial); 370c980fa92SJason Molenda ENUM_TO_CSTR(FunctionChanged); 3716ab659a9SJason Molenda ENUM_TO_CSTR(FunctionIsOptimized); 372554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryFile); 373554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryLineNumber); 374554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryStartAddress); 375554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryEndAddress); 376554f68d3SGreg Clayton ENUM_TO_CSTR(CurrentPCArrow); 377554f68d3SGreg Clayton } 378554f68d3SGreg Clayton return "???"; 379554f68d3SGreg Clayton } 380554f68d3SGreg Clayton 381554f68d3SGreg Clayton #undef ENUM_TO_CSTR 382554f68d3SGreg Clayton 383b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const { 384554f68d3SGreg Clayton s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 385554f68d3SGreg Clayton if (fmt != eFormatDefault) 386554f68d3SGreg Clayton s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); 387554f68d3SGreg Clayton if (!string.empty()) 388554f68d3SGreg Clayton s.Printf("string = \"%s\"", string.c_str()); 389554f68d3SGreg Clayton if (!printf_format.empty()) 390554f68d3SGreg Clayton s.Printf("printf_format = \"%s\"", printf_format.c_str()); 391554f68d3SGreg Clayton if (number != 0) 392554f68d3SGreg Clayton s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 393554f68d3SGreg Clayton if (deref) 394554f68d3SGreg Clayton s.Printf("deref = true, "); 395554f68d3SGreg Clayton s.EOL(); 396b9c1b51eSKate Stone for (const auto &child : children) { 397554f68d3SGreg Clayton child.Dump(s, depth + 1); 398554f68d3SGreg Clayton } 399554f68d3SGreg Clayton } 400554f68d3SGreg Clayton 401554f68d3SGreg Clayton template <typename T> 402b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, 403b9c1b51eSKate Stone const ExecutionContext *exe_ctx, T t, 404b9c1b51eSKate Stone const char *script_function_name) { 405554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 406554f68d3SGreg Clayton 407b9c1b51eSKate Stone if (target) { 408b9c1b51eSKate Stone ScriptInterpreter *script_interpreter = 409b9c1b51eSKate Stone target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 410b9c1b51eSKate Stone if (script_interpreter) { 411554f68d3SGreg Clayton Error error; 412554f68d3SGreg Clayton std::string script_output; 413554f68d3SGreg Clayton 414b9c1b51eSKate Stone if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, 415b9c1b51eSKate Stone script_output, error) && 416b9c1b51eSKate Stone error.Success()) { 417554f68d3SGreg Clayton s.Printf("%s", script_output.c_str()); 418554f68d3SGreg Clayton return true; 419b9c1b51eSKate Stone } else { 420554f68d3SGreg Clayton s.Printf("<error: %s>", error.AsCString()); 421554f68d3SGreg Clayton } 422554f68d3SGreg Clayton } 423554f68d3SGreg Clayton } 424554f68d3SGreg Clayton return false; 425554f68d3SGreg Clayton } 426554f68d3SGreg Clayton 427b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc, 428b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address &addr, 429b9c1b51eSKate Stone bool print_file_addr_or_load_addr) { 430554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 431554f68d3SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 432554f68d3SGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 433554f68d3SGreg Clayton vaddr = addr.GetLoadAddress(target); 434554f68d3SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 435554f68d3SGreg Clayton vaddr = addr.GetFileAddress(); 436554f68d3SGreg Clayton 437b9c1b51eSKate Stone if (vaddr != LLDB_INVALID_ADDRESS) { 438554f68d3SGreg Clayton int addr_width = 0; 439b9c1b51eSKate Stone if (exe_ctx && target) { 440554f68d3SGreg Clayton addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 441554f68d3SGreg Clayton } 442554f68d3SGreg Clayton if (addr_width == 0) 443554f68d3SGreg Clayton addr_width = 16; 444b9c1b51eSKate Stone if (print_file_addr_or_load_addr) { 445a74f37a5SEugene Zelenko ExecutionContextScope *exe_scope = nullptr; 446554f68d3SGreg Clayton if (exe_ctx) 447554f68d3SGreg Clayton exe_scope = exe_ctx->GetBestExecutionContextScope(); 448b9c1b51eSKate Stone addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, 449b9c1b51eSKate Stone Address::DumpStyleModuleWithFileAddress, 0); 450b9c1b51eSKate Stone } else { 451554f68d3SGreg Clayton s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 452554f68d3SGreg Clayton } 453554f68d3SGreg Clayton return true; 454554f68d3SGreg Clayton } 455554f68d3SGreg Clayton return false; 456554f68d3SGreg Clayton } 457554f68d3SGreg Clayton 458b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, 459554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 460554f68d3SGreg Clayton const Address &format_addr, 461b9c1b51eSKate Stone bool concrete_only, bool no_padding, 462b9c1b51eSKate Stone bool print_zero_offsets) { 463b9c1b51eSKate Stone if (format_addr.IsValid()) { 464554f68d3SGreg Clayton Address func_addr; 465554f68d3SGreg Clayton 466b9c1b51eSKate Stone if (sc) { 467b9c1b51eSKate Stone if (sc->function) { 468554f68d3SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 469b9c1b51eSKate Stone if (sc->block && !concrete_only) { 470554f68d3SGreg Clayton // Check to make sure we aren't in an inline 471554f68d3SGreg Clayton // function. If we are, use the inline block 472554f68d3SGreg Clayton // range that contains "format_addr" since 473554f68d3SGreg Clayton // blocks can be discontiguous. 474554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 475554f68d3SGreg Clayton AddressRange inline_range; 476b9c1b51eSKate Stone if (inline_block && 477b9c1b51eSKate Stone inline_block->GetRangeContainingAddress(format_addr, 478b9c1b51eSKate Stone inline_range)) 479554f68d3SGreg Clayton func_addr = inline_range.GetBaseAddress(); 480554f68d3SGreg Clayton } 481b9c1b51eSKate Stone } else if (sc->symbol && sc->symbol->ValueIsAddress()) 482358cf1eaSGreg Clayton func_addr = sc->symbol->GetAddressRef(); 483554f68d3SGreg Clayton } 484554f68d3SGreg Clayton 485b9c1b51eSKate Stone if (func_addr.IsValid()) { 486554f68d3SGreg Clayton const char *addr_offset_padding = no_padding ? "" : " "; 487554f68d3SGreg Clayton 488b9c1b51eSKate Stone if (func_addr.GetSection() == format_addr.GetSection()) { 489554f68d3SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 490554f68d3SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 491b9c1b51eSKate Stone if (addr_file_addr > func_file_addr || 492b9c1b51eSKate Stone (addr_file_addr == func_file_addr && print_zero_offsets)) { 493b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 494b9c1b51eSKate Stone addr_file_addr - func_file_addr); 495b9c1b51eSKate Stone } else if (addr_file_addr < func_file_addr) { 496b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 497b9c1b51eSKate Stone func_file_addr - addr_file_addr); 498c980fa92SJason Molenda } 499554f68d3SGreg Clayton return true; 500b9c1b51eSKate Stone } else { 501554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 502b9c1b51eSKate Stone if (target) { 503554f68d3SGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress(target); 504554f68d3SGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress(target); 505b9c1b51eSKate Stone if (addr_load_addr > func_load_addr || 506b9c1b51eSKate Stone (addr_load_addr == func_load_addr && print_zero_offsets)) { 507b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 508b9c1b51eSKate Stone addr_load_addr - func_load_addr); 509b9c1b51eSKate Stone } else if (addr_load_addr < func_load_addr) { 510b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 511b9c1b51eSKate Stone func_load_addr - addr_load_addr); 512c980fa92SJason Molenda } 513554f68d3SGreg Clayton return true; 514554f68d3SGreg Clayton } 515554f68d3SGreg Clayton } 516554f68d3SGreg Clayton } 517554f68d3SGreg Clayton } 518554f68d3SGreg Clayton return false; 519554f68d3SGreg Clayton } 520554f68d3SGreg Clayton 521b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath, 522554f68d3SGreg Clayton size_t &close_bracket_index, 523554f68d3SGreg Clayton const char *&var_name_final_if_array_range, 524b9c1b51eSKate Stone int64_t &index_lower, int64_t &index_higher) { 5254edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 526554f68d3SGreg Clayton close_bracket_index = llvm::StringRef::npos; 527554f68d3SGreg Clayton const size_t open_bracket_index = subpath.find('['); 528b9c1b51eSKate Stone if (open_bracket_index == llvm::StringRef::npos) { 529554f68d3SGreg Clayton if (log) 530554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 531554f68d3SGreg Clayton return false; 532554f68d3SGreg Clayton } 533554f68d3SGreg Clayton 534554f68d3SGreg Clayton close_bracket_index = subpath.find(']', open_bracket_index + 1); 535554f68d3SGreg Clayton 536b9c1b51eSKate Stone if (close_bracket_index == llvm::StringRef::npos) { 537554f68d3SGreg Clayton if (log) 538554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 539554f68d3SGreg Clayton return false; 540b9c1b51eSKate Stone } else { 541554f68d3SGreg Clayton var_name_final_if_array_range = subpath.data() + open_bracket_index; 542554f68d3SGreg Clayton 543b9c1b51eSKate Stone if (close_bracket_index - open_bracket_index == 1) { 544554f68d3SGreg Clayton if (log) 545b9c1b51eSKate Stone log->Printf( 546b9c1b51eSKate Stone "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 547554f68d3SGreg Clayton index_lower = 0; 548b9c1b51eSKate Stone } else { 549554f68d3SGreg Clayton const size_t separator_index = subpath.find('-', open_bracket_index + 1); 550554f68d3SGreg Clayton 551b9c1b51eSKate Stone if (separator_index == llvm::StringRef::npos) { 552554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 553a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 554554f68d3SGreg Clayton index_higher = index_lower; 555554f68d3SGreg Clayton if (log) 556b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 557b9c1b51eSKate Stone "] detected, high index is same", 558b9c1b51eSKate Stone index_lower); 559b9c1b51eSKate Stone } else { 560554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 561554f68d3SGreg Clayton const char *index_higher_cstr = subpath.data() + separator_index + 1; 562a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 563a74f37a5SEugene Zelenko index_higher = ::strtoul(index_higher_cstr, nullptr, 0); 564554f68d3SGreg Clayton if (log) 565b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", 566b9c1b51eSKate Stone index_lower, index_higher); 567554f68d3SGreg Clayton } 568b9c1b51eSKate Stone if (index_lower > index_higher && index_higher > 0) { 569554f68d3SGreg Clayton if (log) 570554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] swapping indices"); 571554f68d3SGreg Clayton const int64_t temp = index_lower; 572554f68d3SGreg Clayton index_lower = index_higher; 573554f68d3SGreg Clayton index_higher = temp; 574554f68d3SGreg Clayton } 575554f68d3SGreg Clayton } 576554f68d3SGreg Clayton } 577554f68d3SGreg Clayton return true; 578554f68d3SGreg Clayton } 579554f68d3SGreg Clayton 580b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { 581b9c1b51eSKate Stone switch (file_kind) { 582554f68d3SGreg Clayton case FileKind::FileError: 583554f68d3SGreg Clayton break; 584554f68d3SGreg Clayton 585554f68d3SGreg Clayton case FileKind::Basename: 586b9c1b51eSKate Stone if (file.GetFilename()) { 587554f68d3SGreg Clayton s << file.GetFilename(); 588554f68d3SGreg Clayton return true; 589554f68d3SGreg Clayton } 590554f68d3SGreg Clayton break; 591554f68d3SGreg Clayton 592554f68d3SGreg Clayton case FileKind::Dirname: 593b9c1b51eSKate Stone if (file.GetDirectory()) { 594554f68d3SGreg Clayton s << file.GetDirectory(); 595554f68d3SGreg Clayton return true; 596554f68d3SGreg Clayton } 597554f68d3SGreg Clayton break; 598554f68d3SGreg Clayton 599554f68d3SGreg Clayton case FileKind::Fullpath: 600b9c1b51eSKate Stone if (file) { 601554f68d3SGreg Clayton s << file; 602554f68d3SGreg Clayton return true; 603554f68d3SGreg Clayton } 604554f68d3SGreg Clayton break; 605554f68d3SGreg Clayton } 606554f68d3SGreg Clayton return false; 607554f68d3SGreg Clayton } 608554f68d3SGreg Clayton 609b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, 610b9c1b51eSKate Stone uint32_t reg_num, Format format) 611554f68d3SGreg Clayton 612554f68d3SGreg Clayton { 613b9c1b51eSKate Stone if (frame) { 614554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 615554f68d3SGreg Clayton 616b9c1b51eSKate Stone if (reg_ctx) { 617b9c1b51eSKate Stone const uint32_t lldb_reg_num = 618b9c1b51eSKate Stone reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 619b9c1b51eSKate Stone if (lldb_reg_num != LLDB_INVALID_REGNUM) { 620b9c1b51eSKate Stone const RegisterInfo *reg_info = 621b9c1b51eSKate Stone reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); 622b9c1b51eSKate Stone if (reg_info) { 623554f68d3SGreg Clayton RegisterValue reg_value; 624b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 625554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 626554f68d3SGreg Clayton return true; 627554f68d3SGreg Clayton } 628554f68d3SGreg Clayton } 629554f68d3SGreg Clayton } 630554f68d3SGreg Clayton } 631554f68d3SGreg Clayton } 632554f68d3SGreg Clayton return false; 633554f68d3SGreg Clayton } 634554f68d3SGreg Clayton 635b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, 636554f68d3SGreg Clayton StackFrame *frame, 637b9c1b51eSKate Stone bool deref_pointer) { 6384edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 639554f68d3SGreg Clayton const char *ptr_deref_format = "[%d]"; 640554f68d3SGreg Clayton std::string ptr_deref_buffer(10, 0); 641554f68d3SGreg Clayton ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 642554f68d3SGreg Clayton if (log) 643b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] name to deref: %s", 644b9c1b51eSKate Stone ptr_deref_buffer.c_str()); 645554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 646554f68d3SGreg Clayton ValueObject::ExpressionPathEndResultType final_value_type; 647554f68d3SGreg Clayton ValueObject::ExpressionPathScanEndReason reason_to_stop; 648b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 649b9c1b51eSKate Stone (deref_pointer ? ValueObject::eExpressionPathAftermathDereference 650b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 651b9c1b51eSKate Stone ValueObjectSP item = valobj->GetValueForExpressionPath( 652d2daca77SZachary Turner ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, 653d2daca77SZachary Turner &what_next); 654b9c1b51eSKate Stone if (!item) { 655554f68d3SGreg Clayton if (log) 656d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d," 657554f68d3SGreg Clayton " final_value_type %d", 658d2daca77SZachary Turner reason_to_stop, final_value_type); 659b9c1b51eSKate Stone } else { 660554f68d3SGreg Clayton if (log) 661d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," 662554f68d3SGreg Clayton " final_value_type %d", 663d2daca77SZachary Turner reason_to_stop, final_value_type); 664554f68d3SGreg Clayton } 665554f68d3SGreg Clayton return item; 666554f68d3SGreg Clayton } 667554f68d3SGreg Clayton 668b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar( 669b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle style) { 670b9c1b51eSKate Stone switch (style) { 671b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: 672b9c1b51eSKate Stone return '@'; 673b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleValue: 674b9c1b51eSKate Stone return 'V'; 675b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLocation: 676b9c1b51eSKate Stone return 'L'; 677b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleSummary: 678b9c1b51eSKate Stone return 'S'; 679b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleChildrenCount: 680b9c1b51eSKate Stone return '#'; 681b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleType: 682b9c1b51eSKate Stone return 'T'; 683b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleName: 684b9c1b51eSKate Stone return 'N'; 685b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleExpressionPath: 686b9c1b51eSKate Stone return '>'; 687554f68d3SGreg Clayton } 688554f68d3SGreg Clayton return '\0'; 689554f68d3SGreg Clayton } 690554f68d3SGreg Clayton 691b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc, 692554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 693b9c1b51eSKate Stone const FormatEntity::Entry &entry, ValueObject *valobj) { 694a74f37a5SEugene Zelenko if (valobj == nullptr) 695554f68d3SGreg Clayton return false; 696554f68d3SGreg Clayton 6974edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 698554f68d3SGreg Clayton Format custom_format = eFormatInvalid; 699b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle val_obj_display = 700b9c1b51eSKate Stone entry.string.empty() 701b9c1b51eSKate Stone ? ValueObject::eValueObjectRepresentationStyleValue 702b9c1b51eSKate Stone : ValueObject::eValueObjectRepresentationStyleSummary; 703554f68d3SGreg Clayton 704554f68d3SGreg Clayton bool do_deref_pointer = entry.deref; 705554f68d3SGreg Clayton bool is_script = false; 706b9c1b51eSKate Stone switch (entry.type) { 707554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariable: 708554f68d3SGreg Clayton is_script = true; 709554f68d3SGreg Clayton break; 710554f68d3SGreg Clayton 711554f68d3SGreg Clayton case FormatEntity::Entry::Type::Variable: 712554f68d3SGreg Clayton custom_format = entry.fmt; 713554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 714554f68d3SGreg Clayton break; 715554f68d3SGreg Clayton 716554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariableSynthetic: 717554f68d3SGreg Clayton is_script = true; 71862e0681aSJason Molenda LLVM_FALLTHROUGH; 719554f68d3SGreg Clayton case FormatEntity::Entry::Type::VariableSynthetic: 720554f68d3SGreg Clayton custom_format = entry.fmt; 721554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 722b9c1b51eSKate Stone if (!valobj->IsSynthetic()) { 723554f68d3SGreg Clayton valobj = valobj->GetSyntheticValue().get(); 724554f68d3SGreg Clayton if (valobj == nullptr) 725554f68d3SGreg Clayton return false; 726554f68d3SGreg Clayton } 727554f68d3SGreg Clayton break; 728554f68d3SGreg Clayton 729554f68d3SGreg Clayton default: 730554f68d3SGreg Clayton return false; 731554f68d3SGreg Clayton } 732554f68d3SGreg Clayton 733a74f37a5SEugene Zelenko if (valobj == nullptr) 734554f68d3SGreg Clayton return false; 735554f68d3SGreg Clayton 736b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 737b9c1b51eSKate Stone (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference 738b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 739554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 740b9c1b51eSKate Stone options.DontCheckDotVsArrowSyntax() 741b9c1b51eSKate Stone .DoAllowBitfieldSyntax() 742b9c1b51eSKate Stone .DoAllowFragileIVar() 743b9c1b51eSKate Stone .SetSyntheticChildrenTraversal( 744b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions:: 745b9c1b51eSKate Stone SyntheticChildrenTraversal::Both); 746a74f37a5SEugene Zelenko ValueObject *target = nullptr; 747a74f37a5SEugene Zelenko const char *var_name_final_if_array_range = nullptr; 748554f68d3SGreg Clayton size_t close_bracket_index = llvm::StringRef::npos; 749554f68d3SGreg Clayton int64_t index_lower = -1; 750554f68d3SGreg Clayton int64_t index_higher = -1; 751554f68d3SGreg Clayton bool is_array_range = false; 752554f68d3SGreg Clayton bool was_plain_var = false; 753554f68d3SGreg Clayton bool was_var_format = false; 754554f68d3SGreg Clayton bool was_var_indexed = false; 755b9c1b51eSKate Stone ValueObject::ExpressionPathScanEndReason reason_to_stop = 756b9c1b51eSKate Stone ValueObject::eExpressionPathScanEndReasonEndOfString; 757b9c1b51eSKate Stone ValueObject::ExpressionPathEndResultType final_value_type = 758b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypePlain; 759554f68d3SGreg Clayton 760b9c1b51eSKate Stone if (is_script) { 761554f68d3SGreg Clayton return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); 762554f68d3SGreg Clayton } 763554f68d3SGreg Clayton 764554f68d3SGreg Clayton llvm::StringRef subpath(entry.string); 765554f68d3SGreg Clayton // simplest case ${var}, just print valobj's value 766b9c1b51eSKate Stone if (entry.string.empty()) { 767b9c1b51eSKate Stone if (entry.printf_format.empty() && entry.fmt == eFormatDefault && 768b9c1b51eSKate Stone entry.number == ValueObject::eValueObjectRepresentationStyleValue) 769554f68d3SGreg Clayton was_plain_var = true; 770554f68d3SGreg Clayton else 771554f68d3SGreg Clayton was_var_format = true; 772554f68d3SGreg Clayton target = valobj; 773b9c1b51eSKate Stone } else // this is ${var.something} or multiple .something nested 774554f68d3SGreg Clayton { 775554f68d3SGreg Clayton if (entry.string[0] == '[') 776554f68d3SGreg Clayton was_var_indexed = true; 777b9c1b51eSKate Stone ScanBracketedRange(subpath, close_bracket_index, 778b9c1b51eSKate Stone var_name_final_if_array_range, index_lower, 779554f68d3SGreg Clayton index_higher); 780554f68d3SGreg Clayton 781554f68d3SGreg Clayton Error error; 782554f68d3SGreg Clayton 783554f68d3SGreg Clayton const std::string &expr_path = entry.string; 784554f68d3SGreg Clayton 785554f68d3SGreg Clayton if (log) 786b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", 787b9c1b51eSKate Stone expr_path.c_str()); 788554f68d3SGreg Clayton 789d2daca77SZachary Turner target = 790d2daca77SZachary Turner valobj 791d2daca77SZachary Turner ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, 792d2daca77SZachary Turner &final_value_type, options, &what_next) 793b9c1b51eSKate Stone .get(); 794554f68d3SGreg Clayton 795b9c1b51eSKate Stone if (!target) { 796554f68d3SGreg Clayton if (log) 797d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d," 798655c4525SZachary Turner " final_value_type %d", 799d2daca77SZachary Turner reason_to_stop, final_value_type); 800554f68d3SGreg Clayton return false; 801b9c1b51eSKate Stone } else { 802554f68d3SGreg Clayton if (log) 803d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," 804655c4525SZachary Turner " final_value_type %d", 805d2daca77SZachary Turner reason_to_stop, final_value_type); 806b9c1b51eSKate Stone target = target 807b9c1b51eSKate Stone ->GetQualifiedRepresentationIfAvailable( 808b9c1b51eSKate Stone target->GetDynamicValueType(), true) 809b9c1b51eSKate Stone .get(); 810554f68d3SGreg Clayton } 811554f68d3SGreg Clayton } 812554f68d3SGreg Clayton 813b9c1b51eSKate Stone is_array_range = 814b9c1b51eSKate Stone (final_value_type == 815b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeBoundedRange || 816b9c1b51eSKate Stone final_value_type == 817b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeUnboundedRange); 818554f68d3SGreg Clayton 819b9c1b51eSKate Stone do_deref_pointer = 820b9c1b51eSKate Stone (what_next == ValueObject::eExpressionPathAftermathDereference); 821554f68d3SGreg Clayton 822b9c1b51eSKate Stone if (do_deref_pointer && !is_array_range) { 823554f68d3SGreg Clayton // I have not deref-ed yet, let's do it 824b9c1b51eSKate Stone // this happens when we are not going through 825b9c1b51eSKate Stone // GetValueForVariableExpressionPath 826554f68d3SGreg Clayton // to get to the target ValueObject 827554f68d3SGreg Clayton Error error; 828554f68d3SGreg Clayton target = target->Dereference(error).get(); 829b9c1b51eSKate Stone if (error.Fail()) { 830554f68d3SGreg Clayton if (log) 831b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", 832b9c1b51eSKate Stone error.AsCString("unknown")); 833554f68d3SGreg Clayton return false; 834554f68d3SGreg Clayton } 835554f68d3SGreg Clayton do_deref_pointer = false; 836554f68d3SGreg Clayton } 837554f68d3SGreg Clayton 838b9c1b51eSKate Stone if (!target) { 839554f68d3SGreg Clayton if (log) 840b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] could not calculate target for " 841b9c1b51eSKate Stone "prompt expression"); 842554f68d3SGreg Clayton return false; 843554f68d3SGreg Clayton } 844554f68d3SGreg Clayton 845554f68d3SGreg Clayton // we do not want to use the summary for a bitfield of type T:n 846554f68d3SGreg Clayton // if we were originally dealing with just a T - that would get 847554f68d3SGreg Clayton // us into an endless recursion 848b9c1b51eSKate Stone if (target->IsBitfield() && was_var_indexed) { 849554f68d3SGreg Clayton // TODO: check for a (T:n)-specific summary - we should still obey that 850554f68d3SGreg Clayton StreamString bitfield_name; 851b9c1b51eSKate Stone bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), 852b9c1b51eSKate Stone target->GetBitfieldBitSize()); 853*2f3df613SZachary Turner auto type_sp = std::make_shared<TypeNameSpecifierImpl>( 854*2f3df613SZachary Turner bitfield_name.GetString(), false); 855b9c1b51eSKate Stone if (val_obj_display == 856b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary && 857b9c1b51eSKate Stone !DataVisualization::GetSummaryForType(type_sp)) 858554f68d3SGreg Clayton val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 859554f68d3SGreg Clayton } 860554f68d3SGreg Clayton 861554f68d3SGreg Clayton // TODO use flags for these 862b9c1b51eSKate Stone const uint32_t type_info_flags = 863b9c1b51eSKate Stone target->GetCompilerType().GetTypeInfo(nullptr); 864554f68d3SGreg Clayton bool is_array = (type_info_flags & eTypeIsArray) != 0; 865554f68d3SGreg Clayton bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 86699558cc4SGreg Clayton bool is_aggregate = target->GetCompilerType().IsAggregateType(); 867554f68d3SGreg Clayton 868b9c1b51eSKate Stone if ((is_array || is_pointer) && (!is_array_range) && 869b9c1b51eSKate Stone val_obj_display == 870b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue) // this should be 871b9c1b51eSKate Stone // wrong, but there 872b9c1b51eSKate Stone // are some 873b9c1b51eSKate Stone // exceptions 874554f68d3SGreg Clayton { 875554f68d3SGreg Clayton StreamString str_temp; 876554f68d3SGreg Clayton if (log) 877b9c1b51eSKate Stone log->Printf( 878b9c1b51eSKate Stone "[Debugger::FormatPrompt] I am into array || pointer && !range"); 879554f68d3SGreg Clayton 880b9c1b51eSKate Stone if (target->HasSpecialPrintableRepresentation(val_obj_display, 881b9c1b51eSKate Stone custom_format)) { 882554f68d3SGreg Clayton // try to use the special cases 883b9c1b51eSKate Stone bool success = target->DumpPrintableRepresentation( 884b9c1b51eSKate Stone str_temp, val_obj_display, custom_format); 885554f68d3SGreg Clayton if (log) 886b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] special cases did%s match", 887b9c1b51eSKate Stone success ? "" : "n't"); 888554f68d3SGreg Clayton 889554f68d3SGreg Clayton // should not happen 890554f68d3SGreg Clayton if (success) 891c156427dSZachary Turner s << str_temp.GetString(); 892554f68d3SGreg Clayton return true; 893b9c1b51eSKate Stone } else { 894554f68d3SGreg Clayton if (was_plain_var) // if ${var} 895554f68d3SGreg Clayton { 896554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 897b9c1b51eSKate Stone } else if (is_pointer) // if pointer, value is the address stored 898554f68d3SGreg Clayton { 899b9c1b51eSKate Stone target->DumpPrintableRepresentation( 900b9c1b51eSKate Stone s, val_obj_display, custom_format, 90165d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable); 902554f68d3SGreg Clayton } 903554f68d3SGreg Clayton return true; 904554f68d3SGreg Clayton } 905554f68d3SGreg Clayton } 906554f68d3SGreg Clayton 907b9c1b51eSKate Stone // if directly trying to print ${var}, and this is an aggregate, display a 908b9c1b51eSKate Stone // nice 909554f68d3SGreg Clayton // type @ location message 910b9c1b51eSKate Stone if (is_aggregate && was_plain_var) { 911554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 912554f68d3SGreg Clayton return true; 913554f68d3SGreg Clayton } 914554f68d3SGreg Clayton 915b9c1b51eSKate Stone // if directly trying to print ${var%V}, and this is an aggregate, do not let 916b9c1b51eSKate Stone // the user do it 917b9c1b51eSKate Stone if (is_aggregate && 918b9c1b51eSKate Stone ((was_var_format && 919b9c1b51eSKate Stone val_obj_display == 920b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue))) { 921554f68d3SGreg Clayton s << "<invalid use of aggregate type>"; 922554f68d3SGreg Clayton return true; 923554f68d3SGreg Clayton } 924554f68d3SGreg Clayton 925b9c1b51eSKate Stone if (!is_array_range) { 926554f68d3SGreg Clayton if (log) 927554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 928b9c1b51eSKate Stone return target->DumpPrintableRepresentation(s, val_obj_display, 929b9c1b51eSKate Stone custom_format); 930b9c1b51eSKate Stone } else { 931554f68d3SGreg Clayton if (log) 932554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 933554f68d3SGreg Clayton if (!is_array && !is_pointer) 934554f68d3SGreg Clayton return false; 935554f68d3SGreg Clayton if (log) 936554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] handle as array"); 937e8376261SVince Harron StreamString special_directions_stream; 938554f68d3SGreg Clayton llvm::StringRef special_directions; 939b9c1b51eSKate Stone if (close_bracket_index != llvm::StringRef::npos && 940b9c1b51eSKate Stone subpath.size() > close_bracket_index) { 941554f68d3SGreg Clayton ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); 942b9c1b51eSKate Stone special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", 943554f68d3SGreg Clayton additional_data.GetCString()); 944554f68d3SGreg Clayton 945b9c1b51eSKate Stone if (entry.fmt != eFormatDefault) { 946b9c1b51eSKate Stone const char format_char = 947b9c1b51eSKate Stone FormatManager::GetFormatAsFormatChar(entry.fmt); 948554f68d3SGreg Clayton if (format_char != '\0') 949554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", format_char); 950b9c1b51eSKate Stone else { 951b9c1b51eSKate Stone const char *format_cstr = 952b9c1b51eSKate Stone FormatManager::GetFormatAsCString(entry.fmt); 953554f68d3SGreg Clayton special_directions_stream.Printf("%%%s", format_cstr); 954554f68d3SGreg Clayton } 955b9c1b51eSKate Stone } else if (entry.number != 0) { 956b9c1b51eSKate Stone const char style_char = ConvertValueObjectStyleToChar( 957b9c1b51eSKate Stone (ValueObject::ValueObjectRepresentationStyle)entry.number); 958554f68d3SGreg Clayton if (style_char) 959554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", style_char); 960554f68d3SGreg Clayton } 961554f68d3SGreg Clayton special_directions_stream.PutChar('}'); 962b9c1b51eSKate Stone special_directions = 963b9c1b51eSKate Stone llvm::StringRef(special_directions_stream.GetString()); 964554f68d3SGreg Clayton } 965554f68d3SGreg Clayton 966554f68d3SGreg Clayton // let us display items index_lower thru index_higher of this array 967554f68d3SGreg Clayton s.PutChar('['); 968554f68d3SGreg Clayton 969554f68d3SGreg Clayton if (index_higher < 0) 970554f68d3SGreg Clayton index_higher = valobj->GetNumChildren() - 1; 971554f68d3SGreg Clayton 972b9c1b51eSKate Stone uint32_t max_num_children = 973b9c1b51eSKate Stone target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 974554f68d3SGreg Clayton 975554f68d3SGreg Clayton bool success = true; 976b9c1b51eSKate Stone for (int64_t index = index_lower; index <= index_higher; ++index) { 977b9c1b51eSKate Stone ValueObject *item = 978b9c1b51eSKate Stone ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) 979b9c1b51eSKate Stone .get(); 980554f68d3SGreg Clayton 981b9c1b51eSKate Stone if (!item) { 982554f68d3SGreg Clayton if (log) 983b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " 984b9c1b51eSKate Stone "index %" PRId64, 985b9c1b51eSKate Stone index); 986b9c1b51eSKate Stone } else { 987554f68d3SGreg Clayton if (log) 988b9c1b51eSKate Stone log->Printf( 989b9c1b51eSKate Stone "[Debugger::FormatPrompt] special_directions for child item: %s", 990b9c1b51eSKate Stone special_directions.data() ? special_directions.data() : ""); 991554f68d3SGreg Clayton } 992554f68d3SGreg Clayton 993b9c1b51eSKate Stone if (special_directions.empty()) { 994b9c1b51eSKate Stone success &= item->DumpPrintableRepresentation(s, val_obj_display, 995b9c1b51eSKate Stone custom_format); 996b9c1b51eSKate Stone } else { 997b9c1b51eSKate Stone success &= FormatEntity::FormatStringRef( 998b9c1b51eSKate Stone special_directions, s, sc, exe_ctx, nullptr, item, false, false); 999554f68d3SGreg Clayton } 1000554f68d3SGreg Clayton 1001b9c1b51eSKate Stone if (--max_num_children == 0) { 1002554f68d3SGreg Clayton s.PutCString(", ..."); 1003554f68d3SGreg Clayton break; 1004554f68d3SGreg Clayton } 1005554f68d3SGreg Clayton 1006554f68d3SGreg Clayton if (index < index_higher) 1007554f68d3SGreg Clayton s.PutChar(','); 1008554f68d3SGreg Clayton } 1009554f68d3SGreg Clayton s.PutChar(']'); 1010554f68d3SGreg Clayton return success; 1011554f68d3SGreg Clayton } 1012554f68d3SGreg Clayton } 1013554f68d3SGreg Clayton 1014b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, 1015b9c1b51eSKate Stone Format format) { 1016b9c1b51eSKate Stone if (frame) { 1017554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 1018554f68d3SGreg Clayton 1019b9c1b51eSKate Stone if (reg_ctx) { 1020554f68d3SGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 1021b9c1b51eSKate Stone if (reg_info) { 1022554f68d3SGreg Clayton RegisterValue reg_value; 1023b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 1024554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 1025554f68d3SGreg Clayton return true; 1026554f68d3SGreg Clayton } 1027554f68d3SGreg Clayton } 1028554f68d3SGreg Clayton } 1029554f68d3SGreg Clayton } 1030554f68d3SGreg Clayton return false; 1031554f68d3SGreg Clayton } 1032554f68d3SGreg Clayton 1033b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse( 1034b9c1b51eSKate Stone const FormatEntity::Entry &entry, 1035554f68d3SGreg Clayton const StructuredData::ObjectSP &thread_info_dictionary, 1036b9c1b51eSKate Stone const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { 1037554f68d3SGreg Clayton llvm::StringRef path(entry.string); 1038554f68d3SGreg Clayton 1039b9c1b51eSKate Stone StructuredData::ObjectSP value = 1040b9c1b51eSKate Stone thread_info_dictionary->GetObjectForDotSeparatedPath(path); 1041554f68d3SGreg Clayton 1042b9c1b51eSKate Stone if (value) { 1043b9c1b51eSKate Stone if (value->GetType() == StructuredData::Type::eTypeInteger) { 1044554f68d3SGreg Clayton const char *token_format = "0x%4.4" PRIx64; 1045554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1046554f68d3SGreg Clayton token_format = entry.printf_format.c_str(); 1047554f68d3SGreg Clayton s.Printf(token_format, value->GetAsInteger()->GetValue()); 1048554f68d3SGreg Clayton return true; 1049b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeFloat) { 1050554f68d3SGreg Clayton s.Printf("%f", value->GetAsFloat()->GetValue()); 1051554f68d3SGreg Clayton return true; 1052b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeString) { 1053554f68d3SGreg Clayton s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1054554f68d3SGreg Clayton return true; 1055b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeArray) { 1056b9c1b51eSKate Stone if (value->GetAsArray()->GetSize() > 0) { 1057554f68d3SGreg Clayton s.Printf("%zu", value->GetAsArray()->GetSize()); 1058554f68d3SGreg Clayton return true; 1059554f68d3SGreg Clayton } 1060b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeDictionary) { 1061b9c1b51eSKate Stone s.Printf("%zu", 1062b9c1b51eSKate Stone value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1063554f68d3SGreg Clayton return true; 1064554f68d3SGreg Clayton } 1065554f68d3SGreg Clayton } 1066554f68d3SGreg Clayton 1067554f68d3SGreg Clayton return false; 1068554f68d3SGreg Clayton } 1069554f68d3SGreg Clayton 1070b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) { 1071554f68d3SGreg Clayton return (::strncmp(var_name_begin, var, strlen(var)) == 0); 1072554f68d3SGreg Clayton } 1073554f68d3SGreg Clayton 1074b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, 1075554f68d3SGreg Clayton const SymbolContext *sc, 1076554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1077b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1078554f68d3SGreg Clayton bool function_changed, 1079b9c1b51eSKate Stone bool initial_function) { 1080b9c1b51eSKate Stone if (!format_str.empty()) { 1081554f68d3SGreg Clayton FormatEntity::Entry root; 1082554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1083b9c1b51eSKate Stone if (error.Success()) { 1084b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1085b9c1b51eSKate Stone function_changed, initial_function); 1086554f68d3SGreg Clayton } 1087554f68d3SGreg Clayton } 1088554f68d3SGreg Clayton return false; 1089554f68d3SGreg Clayton } 1090a74f37a5SEugene Zelenko 1091b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s, 1092554f68d3SGreg Clayton const SymbolContext *sc, 1093554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1094b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1095b9c1b51eSKate Stone bool function_changed, bool initial_function) { 1096b9c1b51eSKate Stone if (format && format[0]) { 1097554f68d3SGreg Clayton FormatEntity::Entry root; 1098554f68d3SGreg Clayton llvm::StringRef format_str(format); 1099554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1100b9c1b51eSKate Stone if (error.Success()) { 1101b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1102b9c1b51eSKate Stone function_changed, initial_function); 1103554f68d3SGreg Clayton } 1104554f68d3SGreg Clayton } 1105554f68d3SGreg Clayton return false; 1106554f68d3SGreg Clayton } 1107554f68d3SGreg Clayton 1108b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s, 1109554f68d3SGreg Clayton const SymbolContext *sc, 1110b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address *addr, 1111b9c1b51eSKate Stone ValueObject *valobj, bool function_changed, 1112b9c1b51eSKate Stone bool initial_function) { 1113b9c1b51eSKate Stone switch (entry.type) { 1114554f68d3SGreg Clayton case Entry::Type::Invalid: 1115b9c1b51eSKate Stone case Entry::Type::ParentNumber: // Only used for 1116b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1117b9c1b51eSKate Stone case Entry::Type::ParentString: // Only used for 1118b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1119b9c1b51eSKate Stone case Entry::Type::InsertString: // Only used for 1120b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1121554f68d3SGreg Clayton return false; 1122554f68d3SGreg Clayton 1123554f68d3SGreg Clayton case Entry::Type::Root: 1124b9c1b51eSKate Stone for (const auto &child : entry.children) { 1125b9c1b51eSKate Stone if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, 1126b9c1b51eSKate Stone initial_function)) { 1127554f68d3SGreg Clayton return false; // If any item of root fails, then the formatting fails 1128554f68d3SGreg Clayton } 1129554f68d3SGreg Clayton } 1130554f68d3SGreg Clayton return true; // Only return true if all items succeeded 1131554f68d3SGreg Clayton 1132554f68d3SGreg Clayton case Entry::Type::String: 1133771ef6d4SMalcolm Parsons s.PutCString(entry.string); 1134554f68d3SGreg Clayton return true; 1135554f68d3SGreg Clayton 1136b9c1b51eSKate Stone case Entry::Type::Scope: { 1137554f68d3SGreg Clayton StreamString scope_stream; 1138554f68d3SGreg Clayton bool success = false; 1139b9c1b51eSKate Stone for (const auto &child : entry.children) { 1140b9c1b51eSKate Stone success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, 1141b9c1b51eSKate Stone function_changed, initial_function); 1142554f68d3SGreg Clayton if (!success) 1143554f68d3SGreg Clayton break; 1144554f68d3SGreg Clayton } 1145554f68d3SGreg Clayton // Only if all items in a scope succeed, then do we 1146554f68d3SGreg Clayton // print the output into the main stream 1147554f68d3SGreg Clayton if (success) 1148554f68d3SGreg Clayton s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1149554f68d3SGreg Clayton } 1150554f68d3SGreg Clayton return true; // Scopes always successfully print themselves 1151554f68d3SGreg Clayton 1152554f68d3SGreg Clayton case Entry::Type::Variable: 1153554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 1154554f68d3SGreg Clayton case Entry::Type::ScriptVariable: 1155554f68d3SGreg Clayton case Entry::Type::ScriptVariableSynthetic: 1156a74f37a5SEugene Zelenko return DumpValue(s, sc, exe_ctx, entry, valobj); 1157554f68d3SGreg Clayton 1158554f68d3SGreg Clayton case Entry::Type::AddressFile: 1159554f68d3SGreg Clayton case Entry::Type::AddressLoad: 1160554f68d3SGreg Clayton case Entry::Type::AddressLoadOrFile: 1161a74f37a5SEugene Zelenko return (addr != nullptr && addr->IsValid() && 1162b9c1b51eSKate Stone DumpAddress(s, sc, exe_ctx, *addr, 1163b9c1b51eSKate Stone entry.type == Entry::Type::AddressLoadOrFile)); 1164554f68d3SGreg Clayton 1165554f68d3SGreg Clayton case Entry::Type::ProcessID: 1166b9c1b51eSKate Stone if (exe_ctx) { 1167554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1168b9c1b51eSKate Stone if (process) { 1169554f68d3SGreg Clayton const char *format = "%" PRIu64; 1170554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1171554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1172554f68d3SGreg Clayton s.Printf(format, process->GetID()); 1173554f68d3SGreg Clayton return true; 1174554f68d3SGreg Clayton } 1175554f68d3SGreg Clayton } 1176554f68d3SGreg Clayton return false; 1177554f68d3SGreg Clayton 1178554f68d3SGreg Clayton case Entry::Type::ProcessFile: 1179b9c1b51eSKate Stone if (exe_ctx) { 1180554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1181b9c1b51eSKate Stone if (process) { 1182554f68d3SGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1183b9c1b51eSKate Stone if (exe_module) { 1184554f68d3SGreg Clayton if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1185554f68d3SGreg Clayton return true; 1186554f68d3SGreg Clayton } 1187554f68d3SGreg Clayton } 1188554f68d3SGreg Clayton } 1189554f68d3SGreg Clayton return false; 1190554f68d3SGreg Clayton 1191554f68d3SGreg Clayton case Entry::Type::ScriptProcess: 1192b9c1b51eSKate Stone if (exe_ctx) { 1193554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1194554f68d3SGreg Clayton if (process) 1195b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, process, 1196b9c1b51eSKate Stone entry.string.c_str()); 1197554f68d3SGreg Clayton } 1198554f68d3SGreg Clayton return false; 1199554f68d3SGreg Clayton 1200554f68d3SGreg Clayton case Entry::Type::ThreadID: 1201b9c1b51eSKate Stone if (exe_ctx) { 1202554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1203b9c1b51eSKate Stone if (thread) { 1204554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1205b9c1b51eSKate Stone if (!entry.printf_format.empty()) { 1206554f68d3SGreg Clayton // Watch for the special "tid" format... 1207b9c1b51eSKate Stone if (entry.printf_format == "tid") { 1208b9c1b51eSKate Stone // TODO(zturner): Rather than hardcoding this to be platform 1209b9c1b51eSKate Stone // specific, it should be controlled by a 1210b9c1b51eSKate Stone // setting and the default value of the setting can be different 1211b9c1b51eSKate Stone // depending on the platform. 1212554f68d3SGreg Clayton Target &target = thread->GetProcess()->GetTarget(); 1213554f68d3SGreg Clayton ArchSpec arch(target.GetArchitecture()); 1214b9c1b51eSKate Stone llvm::Triple::OSType ostype = arch.IsValid() 1215b9c1b51eSKate Stone ? arch.GetTriple().getOS() 1216b9c1b51eSKate Stone : llvm::Triple::UnknownOS; 1217b9c1b51eSKate Stone if ((ostype == llvm::Triple::FreeBSD) || 1218750228a6SKamil Rytarowski (ostype == llvm::Triple::Linux) || 1219750228a6SKamil Rytarowski (ostype == llvm::Triple::NetBSD)) { 1220554f68d3SGreg Clayton format = "%" PRIu64; 1221554f68d3SGreg Clayton } 1222b9c1b51eSKate Stone } else { 1223554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1224554f68d3SGreg Clayton } 1225554f68d3SGreg Clayton } 1226554f68d3SGreg Clayton s.Printf(format, thread->GetID()); 1227554f68d3SGreg Clayton return true; 1228554f68d3SGreg Clayton } 1229554f68d3SGreg Clayton } 1230554f68d3SGreg Clayton return false; 1231554f68d3SGreg Clayton 1232554f68d3SGreg Clayton case Entry::Type::ThreadProtocolID: 1233b9c1b51eSKate Stone if (exe_ctx) { 1234554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1235b9c1b51eSKate Stone if (thread) { 1236554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1237554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1238554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1239554f68d3SGreg Clayton s.Printf(format, thread->GetProtocolID()); 1240554f68d3SGreg Clayton return true; 1241554f68d3SGreg Clayton } 1242554f68d3SGreg Clayton } 1243554f68d3SGreg Clayton return false; 1244554f68d3SGreg Clayton 1245554f68d3SGreg Clayton case Entry::Type::ThreadIndexID: 1246b9c1b51eSKate Stone if (exe_ctx) { 1247554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1248b9c1b51eSKate Stone if (thread) { 1249554f68d3SGreg Clayton const char *format = "%" PRIu32; 1250554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1251554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1252554f68d3SGreg Clayton s.Printf(format, thread->GetIndexID()); 1253554f68d3SGreg Clayton return true; 1254554f68d3SGreg Clayton } 1255554f68d3SGreg Clayton } 1256554f68d3SGreg Clayton return false; 1257554f68d3SGreg Clayton 1258554f68d3SGreg Clayton case Entry::Type::ThreadName: 1259b9c1b51eSKate Stone if (exe_ctx) { 1260554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1261b9c1b51eSKate Stone if (thread) { 1262554f68d3SGreg Clayton const char *cstr = thread->GetName(); 1263b9c1b51eSKate Stone if (cstr && cstr[0]) { 1264554f68d3SGreg Clayton s.PutCString(cstr); 1265554f68d3SGreg Clayton return true; 1266554f68d3SGreg Clayton } 1267554f68d3SGreg Clayton } 1268554f68d3SGreg Clayton } 1269554f68d3SGreg Clayton return false; 1270554f68d3SGreg Clayton 1271554f68d3SGreg Clayton case Entry::Type::ThreadQueue: 1272b9c1b51eSKate Stone if (exe_ctx) { 1273554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1274b9c1b51eSKate Stone if (thread) { 1275554f68d3SGreg Clayton const char *cstr = thread->GetQueueName(); 1276b9c1b51eSKate Stone if (cstr && cstr[0]) { 1277554f68d3SGreg Clayton s.PutCString(cstr); 1278554f68d3SGreg Clayton return true; 1279554f68d3SGreg Clayton } 1280554f68d3SGreg Clayton } 1281554f68d3SGreg Clayton } 1282554f68d3SGreg Clayton return false; 1283554f68d3SGreg Clayton 1284554f68d3SGreg Clayton case Entry::Type::ThreadStopReason: 1285b9c1b51eSKate Stone if (exe_ctx) { 1286554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1287b9c1b51eSKate Stone if (thread) { 1288554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1289b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1290554f68d3SGreg Clayton const char *cstr = stop_info_sp->GetDescription(); 1291b9c1b51eSKate Stone if (cstr && cstr[0]) { 1292554f68d3SGreg Clayton s.PutCString(cstr); 1293554f68d3SGreg Clayton return true; 1294554f68d3SGreg Clayton } 1295554f68d3SGreg Clayton } 1296554f68d3SGreg Clayton } 1297554f68d3SGreg Clayton } 1298554f68d3SGreg Clayton return false; 1299554f68d3SGreg Clayton 1300554f68d3SGreg Clayton case Entry::Type::ThreadReturnValue: 1301b9c1b51eSKate Stone if (exe_ctx) { 1302554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1303b9c1b51eSKate Stone if (thread) { 1304554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1305b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1306b9c1b51eSKate Stone ValueObjectSP return_valobj_sp = 1307b9c1b51eSKate Stone StopInfo::GetReturnValueObject(stop_info_sp); 1308b9c1b51eSKate Stone if (return_valobj_sp) { 1309554f68d3SGreg Clayton return_valobj_sp->Dump(s); 1310554f68d3SGreg Clayton return true; 1311554f68d3SGreg Clayton } 1312554f68d3SGreg Clayton } 1313554f68d3SGreg Clayton } 1314554f68d3SGreg Clayton } 1315554f68d3SGreg Clayton return false; 1316554f68d3SGreg Clayton 1317554f68d3SGreg Clayton case Entry::Type::ThreadCompletedExpression: 1318b9c1b51eSKate Stone if (exe_ctx) { 1319554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1320b9c1b51eSKate Stone if (thread) { 1321554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1322b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1323b9c1b51eSKate Stone ExpressionVariableSP expression_var_sp = 1324b9c1b51eSKate Stone StopInfo::GetExpressionVariable(stop_info_sp); 1325b9c1b51eSKate Stone if (expression_var_sp && expression_var_sp->GetValueObject()) { 1326554f68d3SGreg Clayton expression_var_sp->GetValueObject()->Dump(s); 1327554f68d3SGreg Clayton return true; 1328554f68d3SGreg Clayton } 1329554f68d3SGreg Clayton } 1330554f68d3SGreg Clayton } 1331554f68d3SGreg Clayton } 1332554f68d3SGreg Clayton return false; 1333554f68d3SGreg Clayton 1334554f68d3SGreg Clayton case Entry::Type::ScriptThread: 1335b9c1b51eSKate Stone if (exe_ctx) { 1336554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1337554f68d3SGreg Clayton if (thread) 1338b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, thread, 1339b9c1b51eSKate Stone entry.string.c_str()); 1340554f68d3SGreg Clayton } 1341554f68d3SGreg Clayton return false; 1342554f68d3SGreg Clayton 1343554f68d3SGreg Clayton case Entry::Type::ThreadInfo: 1344b9c1b51eSKate Stone if (exe_ctx) { 1345554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1346b9c1b51eSKate Stone if (thread) { 1347554f68d3SGreg Clayton StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1348b9c1b51eSKate Stone if (object_sp && 1349b9c1b51eSKate Stone object_sp->GetType() == StructuredData::Type::eTypeDictionary) { 1350554f68d3SGreg Clayton if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) 1351554f68d3SGreg Clayton return true; 1352554f68d3SGreg Clayton } 1353554f68d3SGreg Clayton } 1354554f68d3SGreg Clayton } 1355554f68d3SGreg Clayton return false; 1356554f68d3SGreg Clayton 1357554f68d3SGreg Clayton case Entry::Type::TargetArch: 1358b9c1b51eSKate Stone if (exe_ctx) { 1359554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1360b9c1b51eSKate Stone if (target) { 1361554f68d3SGreg Clayton const ArchSpec &arch = target->GetArchitecture(); 1362b9c1b51eSKate Stone if (arch.IsValid()) { 1363554f68d3SGreg Clayton s.PutCString(arch.GetArchitectureName()); 1364554f68d3SGreg Clayton return true; 1365554f68d3SGreg Clayton } 1366554f68d3SGreg Clayton } 1367554f68d3SGreg Clayton } 1368554f68d3SGreg Clayton return false; 1369554f68d3SGreg Clayton 1370554f68d3SGreg Clayton case Entry::Type::ScriptTarget: 1371b9c1b51eSKate Stone if (exe_ctx) { 1372554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1373554f68d3SGreg Clayton if (target) 1374b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, target, 1375b9c1b51eSKate Stone entry.string.c_str()); 1376554f68d3SGreg Clayton } 1377554f68d3SGreg Clayton return false; 1378554f68d3SGreg Clayton 1379554f68d3SGreg Clayton case Entry::Type::ModuleFile: 1380b9c1b51eSKate Stone if (sc) { 1381554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1382b9c1b51eSKate Stone if (module) { 1383554f68d3SGreg Clayton if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1384554f68d3SGreg Clayton return true; 1385554f68d3SGreg Clayton } 1386554f68d3SGreg Clayton } 1387554f68d3SGreg Clayton return false; 1388554f68d3SGreg Clayton 1389554f68d3SGreg Clayton case Entry::Type::File: 1390b9c1b51eSKate Stone if (sc) { 1391554f68d3SGreg Clayton CompileUnit *cu = sc->comp_unit; 1392b9c1b51eSKate Stone if (cu) { 1393554f68d3SGreg Clayton // CompileUnit is a FileSpec 1394554f68d3SGreg Clayton if (DumpFile(s, *cu, (FileKind)entry.number)) 1395554f68d3SGreg Clayton return true; 1396554f68d3SGreg Clayton } 1397554f68d3SGreg Clayton } 1398554f68d3SGreg Clayton return false; 1399554f68d3SGreg Clayton 1400dc975670SDawn Perchik case Entry::Type::Lang: 1401b9c1b51eSKate Stone if (sc) { 1402dc975670SDawn Perchik CompileUnit *cu = sc->comp_unit; 1403b9c1b51eSKate Stone if (cu) { 1404b9c1b51eSKate Stone const char *lang_name = 1405b9c1b51eSKate Stone Language::GetNameForLanguageType(cu->GetLanguage()); 1406b9c1b51eSKate Stone if (lang_name) { 1407dc975670SDawn Perchik s.PutCString(lang_name); 1408dc975670SDawn Perchik return true; 1409dc975670SDawn Perchik } 1410dc975670SDawn Perchik } 1411dc975670SDawn Perchik } 1412dc975670SDawn Perchik return false; 1413dc975670SDawn Perchik 1414554f68d3SGreg Clayton case Entry::Type::FrameIndex: 1415b9c1b51eSKate Stone if (exe_ctx) { 1416554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1417b9c1b51eSKate Stone if (frame) { 1418554f68d3SGreg Clayton const char *format = "%" PRIu32; 1419554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1420554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1421554f68d3SGreg Clayton s.Printf(format, frame->GetFrameIndex()); 1422554f68d3SGreg Clayton return true; 1423554f68d3SGreg Clayton } 1424554f68d3SGreg Clayton } 1425554f68d3SGreg Clayton return false; 1426554f68d3SGreg Clayton 1427554f68d3SGreg Clayton case Entry::Type::FrameRegisterPC: 1428b9c1b51eSKate Stone if (exe_ctx) { 1429554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1430b9c1b51eSKate Stone if (frame) { 1431554f68d3SGreg Clayton const Address &pc_addr = frame->GetFrameCodeAddress(); 1432b9c1b51eSKate Stone if (pc_addr.IsValid()) { 1433554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) 1434554f68d3SGreg Clayton return true; 1435554f68d3SGreg Clayton } 1436554f68d3SGreg Clayton } 1437554f68d3SGreg Clayton } 1438554f68d3SGreg Clayton return false; 1439554f68d3SGreg Clayton 1440554f68d3SGreg Clayton case Entry::Type::FrameRegisterSP: 1441b9c1b51eSKate Stone if (exe_ctx) { 1442554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1443b9c1b51eSKate Stone if (frame) { 1444b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 1445b9c1b51eSKate Stone (lldb::Format)entry.number)) 1446554f68d3SGreg Clayton return true; 1447554f68d3SGreg Clayton } 1448554f68d3SGreg Clayton } 1449554f68d3SGreg Clayton return false; 1450554f68d3SGreg Clayton 1451554f68d3SGreg Clayton case Entry::Type::FrameRegisterFP: 1452b9c1b51eSKate Stone if (exe_ctx) { 1453554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1454b9c1b51eSKate Stone if (frame) { 1455b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, 1456b9c1b51eSKate Stone (lldb::Format)entry.number)) 1457554f68d3SGreg Clayton return true; 1458554f68d3SGreg Clayton } 1459554f68d3SGreg Clayton } 1460554f68d3SGreg Clayton return false; 1461554f68d3SGreg Clayton 1462554f68d3SGreg Clayton case Entry::Type::FrameRegisterFlags: 1463b9c1b51eSKate Stone if (exe_ctx) { 1464554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1465b9c1b51eSKate Stone if (frame) { 1466b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, 1467b9c1b51eSKate Stone LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1468554f68d3SGreg Clayton return true; 1469554f68d3SGreg Clayton } 1470554f68d3SGreg Clayton } 1471554f68d3SGreg Clayton return false; 1472554f68d3SGreg Clayton 14736a9767c7SJim Ingham case Entry::Type::FrameNoDebug: 14746a9767c7SJim Ingham if (exe_ctx) { 14756a9767c7SJim Ingham StackFrame *frame = exe_ctx->GetFramePtr(); 14766a9767c7SJim Ingham if (frame) { 14776a9767c7SJim Ingham return !frame->HasDebugInformation(); 14786a9767c7SJim Ingham } 14796a9767c7SJim Ingham } 14806a9767c7SJim Ingham return true; 14816a9767c7SJim Ingham 1482554f68d3SGreg Clayton case Entry::Type::FrameRegisterByName: 1483b9c1b51eSKate Stone if (exe_ctx) { 1484554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1485b9c1b51eSKate Stone if (frame) { 1486b9c1b51eSKate Stone if (DumpRegister(s, frame, entry.string.c_str(), 1487b9c1b51eSKate Stone (lldb::Format)entry.number)) 1488554f68d3SGreg Clayton return true; 1489554f68d3SGreg Clayton } 1490554f68d3SGreg Clayton } 1491554f68d3SGreg Clayton return false; 1492554f68d3SGreg Clayton 1493554f68d3SGreg Clayton case Entry::Type::ScriptFrame: 1494b9c1b51eSKate Stone if (exe_ctx) { 1495554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1496554f68d3SGreg Clayton if (frame) 1497b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, frame, 1498b9c1b51eSKate Stone entry.string.c_str()); 1499554f68d3SGreg Clayton } 1500554f68d3SGreg Clayton return false; 1501554f68d3SGreg Clayton 1502554f68d3SGreg Clayton case Entry::Type::FunctionID: 1503b9c1b51eSKate Stone if (sc) { 1504b9c1b51eSKate Stone if (sc->function) { 1505554f68d3SGreg Clayton s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1506554f68d3SGreg Clayton return true; 1507b9c1b51eSKate Stone } else if (sc->symbol) { 1508554f68d3SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 1509554f68d3SGreg Clayton return true; 1510554f68d3SGreg Clayton } 1511554f68d3SGreg Clayton } 1512554f68d3SGreg Clayton return false; 1513554f68d3SGreg Clayton 1514554f68d3SGreg Clayton case Entry::Type::FunctionDidChange: 1515554f68d3SGreg Clayton return function_changed; 1516554f68d3SGreg Clayton 1517554f68d3SGreg Clayton case Entry::Type::FunctionInitialFunction: 1518554f68d3SGreg Clayton return initial_function; 1519554f68d3SGreg Clayton 1520b9c1b51eSKate Stone case Entry::Type::FunctionName: { 1521d4129b47SEnrico Granata Language *language_plugin = nullptr; 1522d4129b47SEnrico Granata bool language_plugin_handled = false; 1523d4129b47SEnrico Granata StreamString ss; 1524d4129b47SEnrico Granata if (sc->function) 1525d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1526d4129b47SEnrico Granata else if (sc->symbol) 1527d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1528b9c1b51eSKate Stone if (language_plugin) { 1529b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1530b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); 1531d4129b47SEnrico Granata } 1532b9c1b51eSKate Stone if (language_plugin_handled) { 1533c156427dSZachary Turner s << ss.GetString(); 1534d4129b47SEnrico Granata return true; 1535b9c1b51eSKate Stone } else { 1536a74f37a5SEugene Zelenko const char *name = nullptr; 1537554f68d3SGreg Clayton if (sc->function) 1538a74f37a5SEugene Zelenko name = sc->function->GetName().AsCString(nullptr); 1539554f68d3SGreg Clayton else if (sc->symbol) 1540a74f37a5SEugene Zelenko name = sc->symbol->GetName().AsCString(nullptr); 1541b9c1b51eSKate Stone if (name) { 1542554f68d3SGreg Clayton s.PutCString(name); 1543554f68d3SGreg Clayton 1544b9c1b51eSKate Stone if (sc->block) { 1545554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1546b9c1b51eSKate Stone if (inline_block) { 1547b9c1b51eSKate Stone const InlineFunctionInfo *inline_info = 1548b9c1b51eSKate Stone sc->block->GetInlinedFunctionInfo(); 1549b9c1b51eSKate Stone if (inline_info) { 1550554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1551ddaf6a72SGreg Clayton inline_info->GetName(sc->function->GetLanguage()).Dump(&s); 1552554f68d3SGreg Clayton } 1553554f68d3SGreg Clayton } 1554554f68d3SGreg Clayton } 1555554f68d3SGreg Clayton return true; 1556554f68d3SGreg Clayton } 1557554f68d3SGreg Clayton } 1558d4129b47SEnrico Granata } 1559554f68d3SGreg Clayton return false; 1560554f68d3SGreg Clayton 1561b9c1b51eSKate Stone case Entry::Type::FunctionNameNoArgs: { 1562d4129b47SEnrico Granata Language *language_plugin = nullptr; 1563d4129b47SEnrico Granata bool language_plugin_handled = false; 1564d4129b47SEnrico Granata StreamString ss; 1565d4129b47SEnrico Granata if (sc->function) 1566d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1567d4129b47SEnrico Granata else if (sc->symbol) 1568d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1569b9c1b51eSKate Stone if (language_plugin) { 1570b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1571b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, 1572d4129b47SEnrico Granata ss); 1573d4129b47SEnrico Granata } 1574b9c1b51eSKate Stone if (language_plugin_handled) { 1575c156427dSZachary Turner s << ss.GetString(); 1576d4129b47SEnrico Granata return true; 1577b9c1b51eSKate Stone } else { 1578554f68d3SGreg Clayton ConstString name; 1579554f68d3SGreg Clayton if (sc->function) 1580ddaf6a72SGreg Clayton name = sc->function->GetNameNoArguments(); 1581554f68d3SGreg Clayton else if (sc->symbol) 1582ddaf6a72SGreg Clayton name = sc->symbol->GetNameNoArguments(); 1583b9c1b51eSKate Stone if (name) { 1584554f68d3SGreg Clayton s.PutCString(name.GetCString()); 1585554f68d3SGreg Clayton return true; 1586554f68d3SGreg Clayton } 1587554f68d3SGreg Clayton } 1588d4129b47SEnrico Granata } 1589554f68d3SGreg Clayton return false; 1590554f68d3SGreg Clayton 1591b9c1b51eSKate Stone case Entry::Type::FunctionNameWithArgs: { 1592d4129b47SEnrico Granata Language *language_plugin = nullptr; 1593d4129b47SEnrico Granata bool language_plugin_handled = false; 1594d4129b47SEnrico Granata StreamString ss; 1595d4129b47SEnrico Granata if (sc->function) 1596d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1597d4129b47SEnrico Granata else if (sc->symbol) 1598d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1599b9c1b51eSKate Stone if (language_plugin) { 1600b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1601b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); 1602d4129b47SEnrico Granata } 1603b9c1b51eSKate Stone if (language_plugin_handled) { 1604c156427dSZachary Turner s << ss.GetString(); 1605d4129b47SEnrico Granata return true; 1606b9c1b51eSKate Stone } else { 1607554f68d3SGreg Clayton // Print the function name with arguments in it 1608b9c1b51eSKate Stone if (sc->function) { 1609b9c1b51eSKate Stone ExecutionContextScope *exe_scope = 1610b9c1b51eSKate Stone exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 1611a74f37a5SEugene Zelenko const char *cstr = sc->function->GetName().AsCString(nullptr); 1612b9c1b51eSKate Stone if (cstr) { 1613a74f37a5SEugene Zelenko const InlineFunctionInfo *inline_info = nullptr; 1614554f68d3SGreg Clayton VariableListSP variable_list_sp; 1615554f68d3SGreg Clayton bool get_function_vars = true; 1616b9c1b51eSKate Stone if (sc->block) { 1617554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1618554f68d3SGreg Clayton 1619b9c1b51eSKate Stone if (inline_block) { 1620554f68d3SGreg Clayton get_function_vars = false; 1621554f68d3SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 1622554f68d3SGreg Clayton if (inline_info) 1623554f68d3SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList(true); 1624554f68d3SGreg Clayton } 1625554f68d3SGreg Clayton } 1626554f68d3SGreg Clayton 1627b9c1b51eSKate Stone if (get_function_vars) { 1628b9c1b51eSKate Stone variable_list_sp = 1629b9c1b51eSKate Stone sc->function->GetBlock(true).GetBlockVariableList(true); 1630554f68d3SGreg Clayton } 1631554f68d3SGreg Clayton 1632b9c1b51eSKate Stone if (inline_info) { 1633554f68d3SGreg Clayton s.PutCString(cstr); 1634554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1635b9c1b51eSKate Stone cstr = 1636b9c1b51eSKate Stone inline_info->GetName(sc->function->GetLanguage()).GetCString(); 1637554f68d3SGreg Clayton } 1638554f68d3SGreg Clayton 1639554f68d3SGreg Clayton VariableList args; 1640554f68d3SGreg Clayton if (variable_list_sp) 1641b9c1b51eSKate Stone variable_list_sp->AppendVariablesWithScope( 1642b9c1b51eSKate Stone eValueTypeVariableArgument, args); 1643b9c1b51eSKate Stone if (args.GetSize() > 0) { 1644554f68d3SGreg Clayton const char *open_paren = strchr(cstr, '('); 1645554f68d3SGreg Clayton const char *close_paren = nullptr; 1646554f68d3SGreg Clayton const char *generic = strchr(cstr, '<'); 1647554f68d3SGreg Clayton // if before the arguments list begins there is a template sign 1648554f68d3SGreg Clayton // then scan to the end of the generic args before you try to find 1649554f68d3SGreg Clayton // the arguments list 1650b9c1b51eSKate Stone if (generic && open_paren && generic < open_paren) { 1651554f68d3SGreg Clayton int generic_depth = 1; 1652554f68d3SGreg Clayton ++generic; 1653b9c1b51eSKate Stone for (; *generic && generic_depth > 0; generic++) { 1654554f68d3SGreg Clayton if (*generic == '<') 1655554f68d3SGreg Clayton generic_depth++; 1656554f68d3SGreg Clayton if (*generic == '>') 1657554f68d3SGreg Clayton generic_depth--; 1658554f68d3SGreg Clayton } 1659554f68d3SGreg Clayton if (*generic) 1660554f68d3SGreg Clayton open_paren = strchr(generic, '('); 1661554f68d3SGreg Clayton else 1662554f68d3SGreg Clayton open_paren = nullptr; 1663554f68d3SGreg Clayton } 1664b9c1b51eSKate Stone if (open_paren) { 1665b9c1b51eSKate Stone if (IsToken(open_paren, "(anonymous namespace)")) { 1666b9c1b51eSKate Stone open_paren = 1667b9c1b51eSKate Stone strchr(open_paren + strlen("(anonymous namespace)"), '('); 1668554f68d3SGreg Clayton if (open_paren) 1669554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1670b9c1b51eSKate Stone } else 1671554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1672554f68d3SGreg Clayton } 1673554f68d3SGreg Clayton 1674554f68d3SGreg Clayton if (open_paren) 1675554f68d3SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 1676b9c1b51eSKate Stone else { 1677554f68d3SGreg Clayton s.PutCString(cstr); 1678554f68d3SGreg Clayton s.PutChar('('); 1679554f68d3SGreg Clayton } 1680554f68d3SGreg Clayton const size_t num_args = args.GetSize(); 1681b9c1b51eSKate Stone for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { 1682554f68d3SGreg Clayton std::string buffer; 1683554f68d3SGreg Clayton 1684554f68d3SGreg Clayton VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); 1685b9c1b51eSKate Stone ValueObjectSP var_value_sp( 1686b9c1b51eSKate Stone ValueObjectVariable::Create(exe_scope, var_sp)); 1687ad91c7ceSEnrico Granata StreamString ss; 1688c156427dSZachary Turner llvm::StringRef var_representation; 1689554f68d3SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 1690b9c1b51eSKate Stone if (var_value_sp->GetCompilerType().IsValid()) { 1691ad91c7ceSEnrico Granata if (var_value_sp && exe_scope->CalculateTarget()) 1692b9c1b51eSKate Stone var_value_sp = 1693b9c1b51eSKate Stone var_value_sp->GetQualifiedRepresentationIfAvailable( 1694b9c1b51eSKate Stone exe_scope->CalculateTarget() 1695b9c1b51eSKate Stone ->TargetProperties::GetPreferDynamicValue(), 1696b9c1b51eSKate Stone exe_scope->CalculateTarget() 1697b9c1b51eSKate Stone ->TargetProperties::GetEnableSyntheticValue()); 169899558cc4SGreg Clayton if (var_value_sp->GetCompilerType().IsAggregateType() && 1699b9c1b51eSKate Stone DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { 1700b9c1b51eSKate Stone static StringSummaryFormat format( 1701b9c1b51eSKate Stone TypeSummaryImpl::Flags() 1702554f68d3SGreg Clayton .SetHideItemNames(false) 1703554f68d3SGreg Clayton .SetShowMembersOneLiner(true), 1704554f68d3SGreg Clayton ""); 1705b9c1b51eSKate Stone format.FormatObject(var_value_sp.get(), buffer, 1706b9c1b51eSKate Stone TypeSummaryOptions()); 1707c156427dSZachary Turner var_representation = buffer; 1708b9c1b51eSKate Stone } else 1709b9c1b51eSKate Stone var_value_sp->DumpPrintableRepresentation( 1710b9c1b51eSKate Stone ss, ValueObject::ValueObjectRepresentationStyle:: 1711b9c1b51eSKate Stone eValueObjectRepresentationStyleSummary, 1712ad91c7ceSEnrico Granata eFormatDefault, 171365d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eAllow, 1714ad91c7ceSEnrico Granata false); 1715ad91c7ceSEnrico Granata } 1716ad91c7ceSEnrico Granata 1717c156427dSZachary Turner if (!ss.GetString().empty()) 1718c156427dSZachary Turner var_representation = ss.GetString(); 1719554f68d3SGreg Clayton if (arg_idx > 0) 1720554f68d3SGreg Clayton s.PutCString(", "); 1721b9c1b51eSKate Stone if (var_value_sp->GetError().Success()) { 1722c156427dSZachary Turner if (!var_representation.empty()) 1723c156427dSZachary Turner s.Printf("%s=%s", var_name, var_representation.str().c_str()); 1724554f68d3SGreg Clayton else 1725b9c1b51eSKate Stone s.Printf("%s=%s at %s", var_name, 1726b9c1b51eSKate Stone var_value_sp->GetTypeName().GetCString(), 1727b9c1b51eSKate Stone var_value_sp->GetLocationAsCString()); 1728b9c1b51eSKate Stone } else 1729554f68d3SGreg Clayton s.Printf("%s=<unavailable>", var_name); 1730554f68d3SGreg Clayton } 1731554f68d3SGreg Clayton 1732554f68d3SGreg Clayton if (close_paren) 1733554f68d3SGreg Clayton s.PutCString(close_paren); 1734554f68d3SGreg Clayton else 1735554f68d3SGreg Clayton s.PutChar(')'); 1736554f68d3SGreg Clayton 1737b9c1b51eSKate Stone } else { 1738554f68d3SGreg Clayton s.PutCString(cstr); 1739554f68d3SGreg Clayton } 1740554f68d3SGreg Clayton return true; 1741554f68d3SGreg Clayton } 1742b9c1b51eSKate Stone } else if (sc->symbol) { 1743a74f37a5SEugene Zelenko const char *cstr = sc->symbol->GetName().AsCString(nullptr); 1744b9c1b51eSKate Stone if (cstr) { 1745554f68d3SGreg Clayton s.PutCString(cstr); 1746554f68d3SGreg Clayton return true; 1747554f68d3SGreg Clayton } 1748554f68d3SGreg Clayton } 1749554f68d3SGreg Clayton } 1750d4129b47SEnrico Granata } 1751554f68d3SGreg Clayton return false; 1752554f68d3SGreg Clayton 1753554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffset: 1754b9c1b51eSKate Stone if (addr) { 1755b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, 1756b9c1b51eSKate Stone false)) 1757554f68d3SGreg Clayton return true; 1758554f68d3SGreg Clayton } 1759554f68d3SGreg Clayton return false; 1760554f68d3SGreg Clayton 1761554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffsetConcrete: 1762b9c1b51eSKate Stone if (addr) { 1763b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, 1764b9c1b51eSKate Stone true)) 1765554f68d3SGreg Clayton return true; 1766554f68d3SGreg Clayton } 1767554f68d3SGreg Clayton return false; 1768554f68d3SGreg Clayton 1769554f68d3SGreg Clayton case Entry::Type::FunctionLineOffset: 1770b9c1b51eSKate Stone return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1771b9c1b51eSKate Stone sc->line_entry.range.GetBaseAddress(), 1772b9c1b51eSKate Stone false, false, false)); 1773554f68d3SGreg Clayton 1774554f68d3SGreg Clayton case Entry::Type::FunctionPCOffset: 1775b9c1b51eSKate Stone if (exe_ctx) { 1776554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1777b9c1b51eSKate Stone if (frame) { 1778b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1779b9c1b51eSKate Stone frame->GetFrameCodeAddress(), false, 1780b9c1b51eSKate Stone false, false)) 1781554f68d3SGreg Clayton return true; 1782554f68d3SGreg Clayton } 1783554f68d3SGreg Clayton } 1784554f68d3SGreg Clayton return false; 1785554f68d3SGreg Clayton 1786c980fa92SJason Molenda case Entry::Type::FunctionChanged: 1787a74f37a5SEugene Zelenko return function_changed; 1788c980fa92SJason Molenda 1789b9c1b51eSKate Stone case Entry::Type::FunctionIsOptimized: { 17906ab659a9SJason Molenda bool is_optimized = false; 1791b9c1b51eSKate Stone if (sc->function && sc->function->GetIsOptimized()) { 17926ab659a9SJason Molenda is_optimized = true; 17936ab659a9SJason Molenda } 17946ab659a9SJason Molenda return is_optimized; 17956ab659a9SJason Molenda } 17966ab659a9SJason Molenda 1797c980fa92SJason Molenda case Entry::Type::FunctionInitial: 1798a74f37a5SEugene Zelenko return initial_function; 1799c980fa92SJason Molenda 1800554f68d3SGreg Clayton case Entry::Type::LineEntryFile: 1801b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1802554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1803b9c1b51eSKate Stone if (module) { 1804554f68d3SGreg Clayton if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1805554f68d3SGreg Clayton return true; 1806554f68d3SGreg Clayton } 1807554f68d3SGreg Clayton } 1808554f68d3SGreg Clayton return false; 1809554f68d3SGreg Clayton 1810554f68d3SGreg Clayton case Entry::Type::LineEntryLineNumber: 1811b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1812554f68d3SGreg Clayton const char *format = "%" PRIu32; 1813554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1814554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1815554f68d3SGreg Clayton s.Printf(format, sc->line_entry.line); 1816554f68d3SGreg Clayton return true; 1817554f68d3SGreg Clayton } 1818554f68d3SGreg Clayton return false; 1819554f68d3SGreg Clayton 1820554f68d3SGreg Clayton case Entry::Type::LineEntryStartAddress: 1821554f68d3SGreg Clayton case Entry::Type::LineEntryEndAddress: 1822b9c1b51eSKate Stone if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { 1823554f68d3SGreg Clayton Address addr = sc->line_entry.range.GetBaseAddress(); 1824554f68d3SGreg Clayton 1825554f68d3SGreg Clayton if (entry.type == Entry::Type::LineEntryEndAddress) 1826554f68d3SGreg Clayton addr.Slide(sc->line_entry.range.GetByteSize()); 1827554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, addr, false)) 1828554f68d3SGreg Clayton return true; 1829554f68d3SGreg Clayton } 1830554f68d3SGreg Clayton return false; 1831554f68d3SGreg Clayton 1832554f68d3SGreg Clayton case Entry::Type::CurrentPCArrow: 1833b9c1b51eSKate Stone if (addr && exe_ctx && exe_ctx->GetFramePtr()) { 1834b9c1b51eSKate Stone RegisterContextSP reg_ctx = 1835b9c1b51eSKate Stone exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1836b9c1b51eSKate Stone if (reg_ctx) { 1837554f68d3SGreg Clayton addr_t pc_loadaddr = reg_ctx->GetPC(); 1838b9c1b51eSKate Stone if (pc_loadaddr != LLDB_INVALID_ADDRESS) { 1839554f68d3SGreg Clayton Address pc; 1840554f68d3SGreg Clayton pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); 1841b9c1b51eSKate Stone if (pc == *addr) { 1842554f68d3SGreg Clayton s.Printf("-> "); 1843554f68d3SGreg Clayton return true; 1844554f68d3SGreg Clayton } 1845554f68d3SGreg Clayton } 1846554f68d3SGreg Clayton } 1847554f68d3SGreg Clayton s.Printf(" "); 1848554f68d3SGreg Clayton return true; 1849554f68d3SGreg Clayton } 1850554f68d3SGreg Clayton return false; 1851554f68d3SGreg Clayton } 1852554f68d3SGreg Clayton return false; 1853554f68d3SGreg Clayton } 1854554f68d3SGreg Clayton 1855b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames( 1856b9c1b51eSKate Stone Stream &s, const FormatEntity::Entry::Definition *parent) { 1857b9c1b51eSKate Stone if (parent->children) { 1858554f68d3SGreg Clayton const size_t n = parent->num_children; 1859b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1860554f68d3SGreg Clayton if (i > 0) 1861554f68d3SGreg Clayton s.PutCString(", "); 1862554f68d3SGreg Clayton s.Printf("\"%s\"", parent->children[i].name); 1863554f68d3SGreg Clayton } 1864554f68d3SGreg Clayton return true; 1865554f68d3SGreg Clayton } 1866554f68d3SGreg Clayton return false; 1867554f68d3SGreg Clayton } 1868554f68d3SGreg Clayton 1869b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str, 1870554f68d3SGreg Clayton const FormatEntity::Entry::Definition *parent, 1871b9c1b51eSKate Stone FormatEntity::Entry &entry) { 1872554f68d3SGreg Clayton Error error; 1873554f68d3SGreg Clayton 1874554f68d3SGreg Clayton const size_t sep_pos = format_str.find_first_of(".[:"); 1875b9c1b51eSKate Stone const char sep_char = 1876b9c1b51eSKate Stone (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1877554f68d3SGreg Clayton llvm::StringRef key = format_str.substr(0, sep_pos); 1878554f68d3SGreg Clayton 1879554f68d3SGreg Clayton const size_t n = parent->num_children; 1880b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1881554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1882b9c1b51eSKate Stone if (key.equals(entry_def->name) || entry_def->name[0] == '*') { 1883554f68d3SGreg Clayton llvm::StringRef value; 1884554f68d3SGreg Clayton if (sep_char) 1885b9c1b51eSKate Stone value = 1886b9c1b51eSKate Stone format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1887b9c1b51eSKate Stone switch (entry_def->type) { 1888554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentString: 18893a29f8b9SPavel Labath entry.string = format_str.str(); 1890554f68d3SGreg Clayton return error; // Success 1891554f68d3SGreg Clayton 1892554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentNumber: 1893554f68d3SGreg Clayton entry.number = entry_def->data; 1894554f68d3SGreg Clayton return error; // Success 1895554f68d3SGreg Clayton 1896554f68d3SGreg Clayton case FormatEntity::Entry::Type::InsertString: 1897554f68d3SGreg Clayton entry.type = entry_def->type; 1898554f68d3SGreg Clayton entry.string = entry_def->string; 1899554f68d3SGreg Clayton return error; // Success 1900554f68d3SGreg Clayton 1901554f68d3SGreg Clayton default: 1902554f68d3SGreg Clayton entry.type = entry_def->type; 1903554f68d3SGreg Clayton break; 1904554f68d3SGreg Clayton } 1905554f68d3SGreg Clayton 1906b9c1b51eSKate Stone if (value.empty()) { 1907b9c1b51eSKate Stone if (entry_def->type == FormatEntity::Entry::Type::Invalid) { 1908b9c1b51eSKate Stone if (entry_def->children) { 1909554f68d3SGreg Clayton StreamString error_strm; 1910b9c1b51eSKate Stone error_strm.Printf("'%s' can't be specified on its own, you must " 1911b9c1b51eSKate Stone "access one of its children: ", 1912b9c1b51eSKate Stone entry_def->name); 1913554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, entry_def); 1914c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1915b9c1b51eSKate Stone } else if (sep_char == ':') { 1916b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1917b9c1b51eSKate Stone // string argument 1918554f68d3SGreg Clayton // that needs to be stored in the entry (like "${script.var:}"). 1919554f68d3SGreg Clayton // In this case the string value is the empty string which is ok. 1920b9c1b51eSKate Stone } else { 1921554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1922554f68d3SGreg Clayton } 1923554f68d3SGreg Clayton } 1924b9c1b51eSKate Stone } else { 1925b9c1b51eSKate Stone if (entry_def->children) { 1926554f68d3SGreg Clayton error = ParseEntry(value, entry_def, entry); 1927b9c1b51eSKate Stone } else if (sep_char == ':') { 1928b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1929b9c1b51eSKate Stone // string argument 1930b9c1b51eSKate Stone // that needs to be stored in the entry (like 1931b9c1b51eSKate Stone // "${script.var:modulename.function}") 19323a29f8b9SPavel Labath entry.string = value.str(); 1933b9c1b51eSKate Stone } else { 1934b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1935b9c1b51eSKate Stone "'%s' followed by '%s' but it has no children", key.str().c_str(), 1936554f68d3SGreg Clayton value.str().c_str()); 1937554f68d3SGreg Clayton } 1938554f68d3SGreg Clayton } 1939554f68d3SGreg Clayton return error; 1940554f68d3SGreg Clayton } 1941554f68d3SGreg Clayton } 1942554f68d3SGreg Clayton StreamString error_strm; 1943554f68d3SGreg Clayton if (parent->type == FormatEntity::Entry::Type::Root) 1944b9c1b51eSKate Stone error_strm.Printf( 1945b9c1b51eSKate Stone "invalid top level item '%s'. Valid top level items are: ", 1946b9c1b51eSKate Stone key.str().c_str()); 1947554f68d3SGreg Clayton else 1948b9c1b51eSKate Stone error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", 1949b9c1b51eSKate Stone key.str().c_str(), parent->name); 1950554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, parent); 1951c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1952554f68d3SGreg Clayton return error; 1953554f68d3SGreg Clayton } 1954554f68d3SGreg Clayton 1955554f68d3SGreg Clayton static const FormatEntity::Entry::Definition * 1956b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str, 1957b9c1b51eSKate Stone const FormatEntity::Entry::Definition *parent, 1958b9c1b51eSKate Stone llvm::StringRef &remainder) { 1959554f68d3SGreg Clayton Error error; 1960554f68d3SGreg Clayton 1961554f68d3SGreg Clayton std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 1962554f68d3SGreg Clayton const size_t n = parent->num_children; 1963b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1964554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1965b9c1b51eSKate Stone if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { 1966b9c1b51eSKate Stone if (p.second.empty()) { 1967554f68d3SGreg Clayton if (format_str.back() == '.') 1968554f68d3SGreg Clayton remainder = format_str.drop_front(format_str.size() - 1); 1969554f68d3SGreg Clayton else 1970554f68d3SGreg Clayton remainder = llvm::StringRef(); // Exact match 1971554f68d3SGreg Clayton return entry_def; 1972b9c1b51eSKate Stone } else { 1973b9c1b51eSKate Stone if (entry_def->children) { 1974554f68d3SGreg Clayton return FindEntry(p.second, entry_def, remainder); 1975b9c1b51eSKate Stone } else { 1976554f68d3SGreg Clayton remainder = p.second; 1977554f68d3SGreg Clayton return entry_def; 1978554f68d3SGreg Clayton } 1979554f68d3SGreg Clayton } 1980554f68d3SGreg Clayton } 1981554f68d3SGreg Clayton } 1982554f68d3SGreg Clayton remainder = format_str; 1983554f68d3SGreg Clayton return parent; 1984554f68d3SGreg Clayton } 1985554f68d3SGreg Clayton 1986b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, 1987b9c1b51eSKate Stone uint32_t depth) { 1988554f68d3SGreg Clayton Error error; 1989b9c1b51eSKate Stone while (!format.empty() && error.Success()) { 1990554f68d3SGreg Clayton const size_t non_special_chars = format.find_first_of("${}\\"); 1991554f68d3SGreg Clayton 1992b9c1b51eSKate Stone if (non_special_chars == llvm::StringRef::npos) { 1993554f68d3SGreg Clayton // No special characters, just string bytes so add them and we are done 1994554f68d3SGreg Clayton parent_entry.AppendText(format); 1995554f68d3SGreg Clayton return error; 1996554f68d3SGreg Clayton } 1997554f68d3SGreg Clayton 1998b9c1b51eSKate Stone if (non_special_chars > 0) { 1999b9c1b51eSKate Stone // We have a special character, so add all characters before these as a 2000b9c1b51eSKate Stone // plain string 2001554f68d3SGreg Clayton parent_entry.AppendText(format.substr(0, non_special_chars)); 2002554f68d3SGreg Clayton format = format.drop_front(non_special_chars); 2003554f68d3SGreg Clayton } 2004554f68d3SGreg Clayton 2005b9c1b51eSKate Stone switch (format[0]) { 2006554f68d3SGreg Clayton case '\0': 2007554f68d3SGreg Clayton return error; 2008554f68d3SGreg Clayton 2009b9c1b51eSKate Stone case '{': { 2010554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2011554f68d3SGreg Clayton Entry scope_entry(Entry::Type::Scope); 2012554f68d3SGreg Clayton error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); 2013554f68d3SGreg Clayton if (error.Fail()) 2014554f68d3SGreg Clayton return error; 2015554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(scope_entry)); 2016b9c1b51eSKate Stone } break; 2017554f68d3SGreg Clayton 2018554f68d3SGreg Clayton case '}': 2019554f68d3SGreg Clayton if (depth == 0) 2020554f68d3SGreg Clayton error.SetErrorString("unmatched '}' character"); 2021554f68d3SGreg Clayton else 2022b9c1b51eSKate Stone format = 2023b9c1b51eSKate Stone format 2024b9c1b51eSKate Stone .drop_front(); // Skip the '}' as we are at the end of the scope 2025554f68d3SGreg Clayton return error; 2026554f68d3SGreg Clayton 2027b9c1b51eSKate Stone case '\\': { 2028554f68d3SGreg Clayton format = format.drop_front(); // Skip the '\' character 2029b9c1b51eSKate Stone if (format.empty()) { 2030b9c1b51eSKate Stone error.SetErrorString( 2031b9c1b51eSKate Stone "'\\' character was not followed by another character"); 2032554f68d3SGreg Clayton return error; 2033554f68d3SGreg Clayton } 2034554f68d3SGreg Clayton 2035554f68d3SGreg Clayton const char desens_char = format[0]; 2036554f68d3SGreg Clayton format = format.drop_front(); // Skip the desensitized char character 2037b9c1b51eSKate Stone switch (desens_char) { 2038b9c1b51eSKate Stone case 'a': 2039b9c1b51eSKate Stone parent_entry.AppendChar('\a'); 2040b9c1b51eSKate Stone break; 2041b9c1b51eSKate Stone case 'b': 2042b9c1b51eSKate Stone parent_entry.AppendChar('\b'); 2043b9c1b51eSKate Stone break; 2044b9c1b51eSKate Stone case 'f': 2045b9c1b51eSKate Stone parent_entry.AppendChar('\f'); 2046b9c1b51eSKate Stone break; 2047b9c1b51eSKate Stone case 'n': 2048b9c1b51eSKate Stone parent_entry.AppendChar('\n'); 2049b9c1b51eSKate Stone break; 2050b9c1b51eSKate Stone case 'r': 2051b9c1b51eSKate Stone parent_entry.AppendChar('\r'); 2052b9c1b51eSKate Stone break; 2053b9c1b51eSKate Stone case 't': 2054b9c1b51eSKate Stone parent_entry.AppendChar('\t'); 2055b9c1b51eSKate Stone break; 2056b9c1b51eSKate Stone case 'v': 2057b9c1b51eSKate Stone parent_entry.AppendChar('\v'); 2058b9c1b51eSKate Stone break; 2059b9c1b51eSKate Stone case '\'': 2060b9c1b51eSKate Stone parent_entry.AppendChar('\''); 2061b9c1b51eSKate Stone break; 2062b9c1b51eSKate Stone case '\\': 2063b9c1b51eSKate Stone parent_entry.AppendChar('\\'); 2064b9c1b51eSKate Stone break; 2065554f68d3SGreg Clayton case '0': 2066554f68d3SGreg Clayton // 1 to 3 octal chars 2067554f68d3SGreg Clayton { 2068554f68d3SGreg Clayton // Make a string that can hold onto the initial zero char, 2069554f68d3SGreg Clayton // up to 3 octal digits, and a terminating NULL. 2070554f68d3SGreg Clayton char oct_str[5] = {0, 0, 0, 0, 0}; 2071554f68d3SGreg Clayton 2072554f68d3SGreg Clayton int i; 2073554f68d3SGreg Clayton for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) 2074554f68d3SGreg Clayton oct_str[i] = format[i]; 2075554f68d3SGreg Clayton 2076554f68d3SGreg Clayton // We don't want to consume the last octal character since 2077554f68d3SGreg Clayton // the main for loop will do this for us, so we advance p by 2078554f68d3SGreg Clayton // one less than i (even if i is zero) 2079554f68d3SGreg Clayton format = format.drop_front(i); 2080a74f37a5SEugene Zelenko unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); 2081b9c1b51eSKate Stone if (octal_value <= UINT8_MAX) { 2082554f68d3SGreg Clayton parent_entry.AppendChar((char)octal_value); 2083b9c1b51eSKate Stone } else { 2084554f68d3SGreg Clayton error.SetErrorString("octal number is larger than a single byte"); 2085554f68d3SGreg Clayton return error; 2086554f68d3SGreg Clayton } 2087554f68d3SGreg Clayton } 2088554f68d3SGreg Clayton break; 2089554f68d3SGreg Clayton 2090554f68d3SGreg Clayton case 'x': 2091554f68d3SGreg Clayton // hex number in the format 2092b9c1b51eSKate Stone if (isxdigit(format[0])) { 2093554f68d3SGreg Clayton // Make a string that can hold onto two hex chars plus a 2094554f68d3SGreg Clayton // NULL terminator 2095554f68d3SGreg Clayton char hex_str[3] = {0, 0, 0}; 2096554f68d3SGreg Clayton hex_str[0] = format[0]; 2097554f68d3SGreg Clayton 2098554f68d3SGreg Clayton format = format.drop_front(); 2099554f68d3SGreg Clayton 2100b9c1b51eSKate Stone if (isxdigit(format[0])) { 2101554f68d3SGreg Clayton hex_str[1] = format[0]; 2102554f68d3SGreg Clayton format = format.drop_front(); 2103554f68d3SGreg Clayton } 2104554f68d3SGreg Clayton 2105a74f37a5SEugene Zelenko unsigned long hex_value = strtoul(hex_str, nullptr, 16); 2106b9c1b51eSKate Stone if (hex_value <= UINT8_MAX) { 2107554f68d3SGreg Clayton parent_entry.AppendChar((char)hex_value); 2108b9c1b51eSKate Stone } else { 2109554f68d3SGreg Clayton error.SetErrorString("hex number is larger than a single byte"); 2110554f68d3SGreg Clayton return error; 2111554f68d3SGreg Clayton } 2112b9c1b51eSKate Stone } else { 2113554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2114554f68d3SGreg Clayton } 2115554f68d3SGreg Clayton break; 2116554f68d3SGreg Clayton 2117554f68d3SGreg Clayton default: 2118554f68d3SGreg Clayton // Just desensitize any other character by just printing what 2119554f68d3SGreg Clayton // came after the '\' 2120554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2121554f68d3SGreg Clayton break; 2122554f68d3SGreg Clayton } 2123b9c1b51eSKate Stone } break; 2124554f68d3SGreg Clayton 2125554f68d3SGreg Clayton case '$': 2126b9c1b51eSKate Stone if (format.size() == 1) { 2127554f68d3SGreg Clayton // '$' at the end of a format string, just print the '$' 2128554f68d3SGreg Clayton parent_entry.AppendText("$"); 2129b9c1b51eSKate Stone } else { 2130554f68d3SGreg Clayton format = format.drop_front(); // Skip the '$' 2131554f68d3SGreg Clayton 2132b9c1b51eSKate Stone if (format[0] == '{') { 2133554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2134554f68d3SGreg Clayton 2135554f68d3SGreg Clayton llvm::StringRef variable, variable_format; 2136b9c1b51eSKate Stone error = FormatEntity::ExtractVariableInfo(format, variable, 2137b9c1b51eSKate Stone variable_format); 2138554f68d3SGreg Clayton if (error.Fail()) 2139554f68d3SGreg Clayton return error; 2140554f68d3SGreg Clayton bool verify_is_thread_id = false; 2141554f68d3SGreg Clayton Entry entry; 2142b9c1b51eSKate Stone if (!variable_format.empty()) { 21433a29f8b9SPavel Labath entry.printf_format = variable_format.str(); 2144554f68d3SGreg Clayton 2145554f68d3SGreg Clayton // If the format contains a '%' we are going to assume this is 2146554f68d3SGreg Clayton // a printf style format. So if you want to format your thread ID 2147554f68d3SGreg Clayton // using "0x%llx" you can use: 2148554f68d3SGreg Clayton // ${thread.id%0x%llx} 2149554f68d3SGreg Clayton // 2150554f68d3SGreg Clayton // If there is no '%' in the format, then it is assumed to be a 2151554f68d3SGreg Clayton // LLDB format name, or one of the extended formats specified in 2152554f68d3SGreg Clayton // the switch statement below. 2153554f68d3SGreg Clayton 2154b9c1b51eSKate Stone if (entry.printf_format.find('%') == std::string::npos) { 2155554f68d3SGreg Clayton bool clear_printf = false; 2156554f68d3SGreg Clayton 2157b9c1b51eSKate Stone if (FormatManager::GetFormatFromCString( 2158b9c1b51eSKate Stone entry.printf_format.c_str(), false, entry.fmt)) { 2159554f68d3SGreg Clayton // We have an LLDB format, so clear the printf format 2160554f68d3SGreg Clayton clear_printf = true; 2161b9c1b51eSKate Stone } else if (entry.printf_format.size() == 1) { 2162b9c1b51eSKate Stone switch (entry.printf_format[0]) { 2163554f68d3SGreg Clayton case '@': // if this is an @ sign, print ObjC description 2164b9c1b51eSKate Stone entry.number = ValueObject:: 2165b9c1b51eSKate Stone eValueObjectRepresentationStyleLanguageSpecific; 2166554f68d3SGreg Clayton clear_printf = true; 2167554f68d3SGreg Clayton break; 2168b9c1b51eSKate Stone case 'V': // if this is a V, print the value using the default 2169b9c1b51eSKate Stone // format 2170b9c1b51eSKate Stone entry.number = 2171b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2172554f68d3SGreg Clayton clear_printf = true; 2173554f68d3SGreg Clayton break; 2174554f68d3SGreg Clayton case 'L': // if this is an L, print the location of the value 2175b9c1b51eSKate Stone entry.number = 2176b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleLocation; 2177554f68d3SGreg Clayton clear_printf = true; 2178554f68d3SGreg Clayton break; 2179554f68d3SGreg Clayton case 'S': // if this is an S, print the summary after all 2180b9c1b51eSKate Stone entry.number = 2181b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2182554f68d3SGreg Clayton clear_printf = true; 2183554f68d3SGreg Clayton break; 2184554f68d3SGreg Clayton case '#': // if this is a '#', print the number of children 2185b9c1b51eSKate Stone entry.number = 2186b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleChildrenCount; 2187554f68d3SGreg Clayton clear_printf = true; 2188554f68d3SGreg Clayton break; 2189554f68d3SGreg Clayton case 'T': // if this is a 'T', print the type 2190b9c1b51eSKate Stone entry.number = 2191b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleType; 2192554f68d3SGreg Clayton clear_printf = true; 2193554f68d3SGreg Clayton break; 2194554f68d3SGreg Clayton case 'N': // if this is a 'N', print the name 2195b9c1b51eSKate Stone entry.number = 2196b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleName; 2197554f68d3SGreg Clayton clear_printf = true; 2198554f68d3SGreg Clayton break; 2199281b65bcSGreg Clayton case '>': // if this is a '>', print the expression path 2200b9c1b51eSKate Stone entry.number = ValueObject:: 2201b9c1b51eSKate Stone eValueObjectRepresentationStyleExpressionPath; 2202554f68d3SGreg Clayton clear_printf = true; 2203554f68d3SGreg Clayton break; 2204554f68d3SGreg Clayton default: 2205b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2206b9c1b51eSKate Stone entry.printf_format.c_str()); 2207554f68d3SGreg Clayton return error; 2208554f68d3SGreg Clayton } 2209b9c1b51eSKate Stone } else if (FormatManager::GetFormatFromCString( 2210b9c1b51eSKate Stone entry.printf_format.c_str(), true, entry.fmt)) { 2211554f68d3SGreg Clayton clear_printf = true; 2212b9c1b51eSKate Stone } else if (entry.printf_format == "tid") { 2213554f68d3SGreg Clayton verify_is_thread_id = true; 2214b9c1b51eSKate Stone } else { 2215b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2216b9c1b51eSKate Stone entry.printf_format.c_str()); 2217554f68d3SGreg Clayton return error; 2218554f68d3SGreg Clayton } 2219554f68d3SGreg Clayton 2220554f68d3SGreg Clayton // Our format string turned out to not be a printf style format 2221554f68d3SGreg Clayton // so lets clear the string 2222554f68d3SGreg Clayton if (clear_printf) 2223554f68d3SGreg Clayton entry.printf_format.clear(); 2224554f68d3SGreg Clayton } 2225554f68d3SGreg Clayton } 2226554f68d3SGreg Clayton 2227554f68d3SGreg Clayton // Check for dereferences 2228b9c1b51eSKate Stone if (variable[0] == '*') { 2229554f68d3SGreg Clayton entry.deref = true; 2230554f68d3SGreg Clayton variable = variable.drop_front(); 2231554f68d3SGreg Clayton } 2232554f68d3SGreg Clayton 2233554f68d3SGreg Clayton error = ParseEntry(variable, &g_root, entry); 2234554f68d3SGreg Clayton if (error.Fail()) 2235554f68d3SGreg Clayton return error; 2236554f68d3SGreg Clayton 2237b9c1b51eSKate Stone if (verify_is_thread_id) { 2238554f68d3SGreg Clayton if (entry.type != Entry::Type::ThreadID && 2239b9c1b51eSKate Stone entry.type != Entry::Type::ThreadProtocolID) { 2240b9c1b51eSKate Stone error.SetErrorString("the 'tid' format can only be used on " 2241b9c1b51eSKate Stone "${thread.id} and ${thread.protocol_id}"); 2242554f68d3SGreg Clayton } 2243554f68d3SGreg Clayton } 2244554f68d3SGreg Clayton 2245b9c1b51eSKate Stone switch (entry.type) { 2246554f68d3SGreg Clayton case Entry::Type::Variable: 2247554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 2248b9c1b51eSKate Stone if (entry.number == 0) { 2249554f68d3SGreg Clayton if (entry.string.empty()) 2250b9c1b51eSKate Stone entry.number = 2251b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2252554f68d3SGreg Clayton else 2253b9c1b51eSKate Stone entry.number = 2254b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2255554f68d3SGreg Clayton } 2256554f68d3SGreg Clayton break; 2257554f68d3SGreg Clayton default: 2258b9c1b51eSKate Stone // Make sure someone didn't try to dereference anything but ${var} 2259b9c1b51eSKate Stone // or ${svar} 2260b9c1b51eSKate Stone if (entry.deref) { 2261b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2262b9c1b51eSKate Stone "${%s} can't be dereferenced, only ${var} and ${svar} can.", 2263b9c1b51eSKate Stone variable.str().c_str()); 2264554f68d3SGreg Clayton return error; 2265554f68d3SGreg Clayton } 2266554f68d3SGreg Clayton } 2267554f68d3SGreg Clayton // Check if this entry just wants to insert a constant string 2268554f68d3SGreg Clayton // value into the parent_entry, if so, insert the string with 2269554f68d3SGreg Clayton // AppendText, else append the entry to the parent_entry. 2270554f68d3SGreg Clayton if (entry.type == Entry::Type::InsertString) 2271554f68d3SGreg Clayton parent_entry.AppendText(entry.string.c_str()); 2272554f68d3SGreg Clayton else 2273554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(entry)); 2274554f68d3SGreg Clayton } 2275554f68d3SGreg Clayton } 2276554f68d3SGreg Clayton break; 2277554f68d3SGreg Clayton } 2278554f68d3SGreg Clayton } 2279554f68d3SGreg Clayton return error; 2280554f68d3SGreg Clayton } 2281554f68d3SGreg Clayton 2282b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, 2283b9c1b51eSKate Stone llvm::StringRef &variable_name, 2284b9c1b51eSKate Stone llvm::StringRef &variable_format) { 2285554f68d3SGreg Clayton Error error; 2286554f68d3SGreg Clayton variable_name = llvm::StringRef(); 2287554f68d3SGreg Clayton variable_format = llvm::StringRef(); 2288554f68d3SGreg Clayton 2289e8433cc1SBruce Mitchener const size_t paren_pos = format_str.find('}'); 2290b9c1b51eSKate Stone if (paren_pos != llvm::StringRef::npos) { 2291e8433cc1SBruce Mitchener const size_t percent_pos = format_str.find('%'); 2292b9c1b51eSKate Stone if (percent_pos < paren_pos) { 2293b9c1b51eSKate Stone if (percent_pos > 0) { 2294554f68d3SGreg Clayton if (percent_pos > 1) 2295554f68d3SGreg Clayton variable_name = format_str.substr(0, percent_pos); 2296b9c1b51eSKate Stone variable_format = 2297b9c1b51eSKate Stone format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2298554f68d3SGreg Clayton } 2299b9c1b51eSKate Stone } else { 2300554f68d3SGreg Clayton variable_name = format_str.substr(0, paren_pos); 2301554f68d3SGreg Clayton } 2302554f68d3SGreg Clayton // Strip off elements and the formatting and the trailing '}' 2303554f68d3SGreg Clayton format_str = format_str.substr(paren_pos + 1); 2304b9c1b51eSKate Stone } else { 2305b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2306b9c1b51eSKate Stone "missing terminating '}' character for '${%s'", 2307b9c1b51eSKate Stone format_str.str().c_str()); 2308554f68d3SGreg Clayton } 2309554f68d3SGreg Clayton return error; 2310554f68d3SGreg Clayton } 2311554f68d3SGreg Clayton 2312b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, 2313b9c1b51eSKate Stone llvm::StringRef variable_name, 2314b9c1b51eSKate Stone llvm::StringRef variable_format) { 2315b9c1b51eSKate Stone if (variable_name.empty() || variable_name.equals(".fullpath")) { 2316554f68d3SGreg Clayton file_spec.Dump(&s); 2317554f68d3SGreg Clayton return true; 2318b9c1b51eSKate Stone } else if (variable_name.equals(".basename")) { 2319554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2320554f68d3SGreg Clayton return true; 2321b9c1b51eSKate Stone } else if (variable_name.equals(".dirname")) { 2322554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2323554f68d3SGreg Clayton return true; 2324554f68d3SGreg Clayton } 2325554f68d3SGreg Clayton return false; 2326554f68d3SGreg Clayton } 2327554f68d3SGreg Clayton 2328b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix, 2329b9c1b51eSKate Stone const char *suffix) { 2330554f68d3SGreg Clayton std::string match(prefix.str()); 2331554f68d3SGreg Clayton match.append(suffix); 23323a29f8b9SPavel Labath return match; 2333554f68d3SGreg Clayton } 2334554f68d3SGreg Clayton 2335b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def, 2336554f68d3SGreg Clayton const llvm::StringRef &prefix, 2337554f68d3SGreg Clayton const llvm::StringRef &match_prefix, 2338b9c1b51eSKate Stone StringList &matches) { 2339554f68d3SGreg Clayton const size_t n = def->num_children; 2340b9c1b51eSKate Stone if (n > 0) { 2341b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 23423a29f8b9SPavel Labath std::string match = prefix.str(); 2343554f68d3SGreg Clayton if (match_prefix.empty()) 2344554f68d3SGreg Clayton matches.AppendString(MakeMatch(prefix, def->children[i].name)); 2345b9c1b51eSKate Stone else if (strncmp(def->children[i].name, match_prefix.data(), 2346b9c1b51eSKate Stone match_prefix.size()) == 0) 2347b9c1b51eSKate Stone matches.AppendString( 2348b9c1b51eSKate Stone MakeMatch(prefix, def->children[i].name + match_prefix.size())); 2349554f68d3SGreg Clayton } 2350554f68d3SGreg Clayton } 2351554f68d3SGreg Clayton } 2352a74f37a5SEugene Zelenko 23534aa8753cSZachary Turner size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, 2354b9c1b51eSKate Stone int max_return_elements, bool &word_complete, 2355b9c1b51eSKate Stone StringList &matches) { 2356554f68d3SGreg Clayton word_complete = false; 23574aa8753cSZachary Turner str = str.drop_front(match_start_point); 2358554f68d3SGreg Clayton matches.Clear(); 2359554f68d3SGreg Clayton 2360554f68d3SGreg Clayton const size_t dollar_pos = str.rfind('$'); 23614aa8753cSZachary Turner if (dollar_pos == llvm::StringRef::npos) 23624aa8753cSZachary Turner return 0; 23634aa8753cSZachary Turner 2364554f68d3SGreg Clayton // Hitting TAB after $ at the end of the string add a "{" 2365b9c1b51eSKate Stone if (dollar_pos == str.size() - 1) { 23663a29f8b9SPavel Labath std::string match = str.str(); 2367554f68d3SGreg Clayton match.append("{"); 23684aa8753cSZachary Turner matches.AppendString(match); 23694aa8753cSZachary Turner return 1; 23704aa8753cSZachary Turner } 23714aa8753cSZachary Turner 23724aa8753cSZachary Turner if (str[dollar_pos + 1] != '{') 23734aa8753cSZachary Turner return 0; 23744aa8753cSZachary Turner 2375554f68d3SGreg Clayton const size_t close_pos = str.find('}', dollar_pos + 2); 23764aa8753cSZachary Turner if (close_pos != llvm::StringRef::npos) 23774aa8753cSZachary Turner return 0; 23784aa8753cSZachary Turner 2379554f68d3SGreg Clayton const size_t format_pos = str.find('%', dollar_pos + 2); 23804aa8753cSZachary Turner if (format_pos != llvm::StringRef::npos) 23814aa8753cSZachary Turner return 0; 23824aa8753cSZachary Turner 2383554f68d3SGreg Clayton llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); 2384b9c1b51eSKate Stone if (partial_variable.empty()) { 2385554f68d3SGreg Clayton // Suggest all top level entites as we are just past "${" 2386554f68d3SGreg Clayton AddMatches(&g_root, str, llvm::StringRef(), matches); 23874aa8753cSZachary Turner return matches.GetSize(); 23884aa8753cSZachary Turner } 23894aa8753cSZachary Turner 2390554f68d3SGreg Clayton // We have a partially specified variable, find it 2391554f68d3SGreg Clayton llvm::StringRef remainder; 2392b9c1b51eSKate Stone const FormatEntity::Entry::Definition *entry_def = 2393b9c1b51eSKate Stone FindEntry(partial_variable, &g_root, remainder); 23944aa8753cSZachary Turner if (!entry_def) 23954aa8753cSZachary Turner return 0; 23964aa8753cSZachary Turner 2397554f68d3SGreg Clayton const size_t n = entry_def->num_children; 2398554f68d3SGreg Clayton 2399b9c1b51eSKate Stone if (remainder.empty()) { 2400554f68d3SGreg Clayton // Exact match 2401b9c1b51eSKate Stone if (n > 0) { 2402554f68d3SGreg Clayton // "${thread.info" <TAB> 24033a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, ".")); 2404b9c1b51eSKate Stone } else { 2405554f68d3SGreg Clayton // "${thread.id" <TAB> 24063a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, "}")); 2407554f68d3SGreg Clayton word_complete = true; 2408554f68d3SGreg Clayton } 2409b9c1b51eSKate Stone } else if (remainder.equals(".")) { 2410554f68d3SGreg Clayton // "${thread." <TAB> 2411554f68d3SGreg Clayton AddMatches(entry_def, str, llvm::StringRef(), matches); 2412b9c1b51eSKate Stone } else { 2413554f68d3SGreg Clayton // We have a partial match 2414554f68d3SGreg Clayton // "${thre" <TAB> 2415554f68d3SGreg Clayton AddMatches(entry_def, str, remainder, matches); 2416554f68d3SGreg Clayton } 2417554f68d3SGreg Clayton return matches.GetSize(); 2418554f68d3SGreg Clayton } 2419