180814287SRaphael Isemann //===-- FormatEntity.cpp --------------------------------------------------===// 2554f68d3SGreg Clayton // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6554f68d3SGreg Clayton // 7554f68d3SGreg Clayton //===----------------------------------------------------------------------===// 8554f68d3SGreg Clayton 9554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 10554f68d3SGreg Clayton 11554f68d3SGreg Clayton #include "lldb/Core/Address.h" 12672d2c12SJonas Devlieghere #include "lldb/Core/AddressRange.h" 13554f68d3SGreg Clayton #include "lldb/Core/Debugger.h" 14e03334cfSPavel Labath #include "lldb/Core/DumpRegisterValue.h" 15554f68d3SGreg Clayton #include "lldb/Core/Module.h" 16554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h" 17554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 18554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h" 19672d2c12SJonas Devlieghere #include "lldb/DataFormatters/FormatClasses.h" 20554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h" 21672d2c12SJonas Devlieghere #include "lldb/DataFormatters/TypeSummary.h" 22937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h" 23554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 24554f68d3SGreg Clayton #include "lldb/Symbol/Block.h" 25554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 26672d2c12SJonas Devlieghere #include "lldb/Symbol/CompilerType.h" 27554f68d3SGreg Clayton #include "lldb/Symbol/Function.h" 28554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h" 29554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h" 30672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 31554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h" 32554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h" 33672d2c12SJonas Devlieghere #include "lldb/Target/ExecutionContextScope.h" 340e0984eeSJim Ingham #include "lldb/Target/Language.h" 35554f68d3SGreg Clayton #include "lldb/Target/Process.h" 36554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h" 37554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h" 38554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h" 39554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h" 40554f68d3SGreg Clayton #include "lldb/Target/Target.h" 41554f68d3SGreg Clayton #include "lldb/Target/Thread.h" 42554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 43672d2c12SJonas Devlieghere #include "lldb/Utility/ArchSpec.h" 44672d2c12SJonas Devlieghere #include "lldb/Utility/ConstString.h" 455713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 46672d2c12SJonas Devlieghere #include "lldb/Utility/Log.h" 47672d2c12SJonas Devlieghere #include "lldb/Utility/Logging.h" 48672d2c12SJonas Devlieghere #include "lldb/Utility/RegisterValue.h" 49bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 50bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 51672d2c12SJonas Devlieghere #include "lldb/Utility/StringList.h" 52672d2c12SJonas Devlieghere #include "lldb/Utility/StructuredData.h" 53672d2c12SJonas Devlieghere #include "lldb/lldb-defines.h" 54672d2c12SJonas Devlieghere #include "lldb/lldb-forward.h" 552f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" 562f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 57672d2c12SJonas Devlieghere #include "llvm/ADT/Triple.h" 58672d2c12SJonas Devlieghere #include "llvm/Support/Compiler.h" 592f3df613SZachary Turner 60672d2c12SJonas Devlieghere #include <ctype.h> 61672d2c12SJonas Devlieghere #include <inttypes.h> 62672d2c12SJonas Devlieghere #include <memory> 63672d2c12SJonas Devlieghere #include <stdio.h> 64672d2c12SJonas Devlieghere #include <stdlib.h> 65672d2c12SJonas Devlieghere #include <string.h> 66672d2c12SJonas Devlieghere #include <type_traits> 67672d2c12SJonas Devlieghere #include <utility> 682f3df613SZachary Turner 692f3df613SZachary Turner namespace lldb_private { 702f3df613SZachary Turner class ScriptInterpreter; 712f3df613SZachary Turner } 722f3df613SZachary Turner namespace lldb_private { 732f3df613SZachary Turner struct RegisterInfo; 742f3df613SZachary Turner } 75554f68d3SGreg Clayton 76554f68d3SGreg Clayton using namespace lldb; 77554f68d3SGreg Clayton using namespace lldb_private; 78554f68d3SGreg Clayton 79b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath }; 80554f68d3SGreg Clayton 8140dfc392SJonas Devlieghere #define ENTRY(n, t) \ 8240dfc392SJonas Devlieghere { n, nullptr, FormatEntity::Entry::Type::t, 0, 0, nullptr, false } 8340dfc392SJonas Devlieghere #define ENTRY_VALUE(n, t, v) \ 8440dfc392SJonas Devlieghere { n, nullptr, FormatEntity::Entry::Type::t, v, 0, nullptr, false } 8540dfc392SJonas Devlieghere #define ENTRY_CHILDREN(n, t, c) \ 86b9c1b51eSKate Stone { \ 8740dfc392SJonas Devlieghere n, nullptr, FormatEntity::Entry::Type::t, 0, \ 88e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \ 89b9c1b51eSKate Stone } 9040dfc392SJonas Devlieghere #define ENTRY_CHILDREN_KEEP_SEP(n, t, c) \ 91b9c1b51eSKate Stone { \ 9240dfc392SJonas Devlieghere n, nullptr, FormatEntity::Entry::Type::t, 0, \ 93e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, true \ 94b9c1b51eSKate Stone } 95b9c1b51eSKate Stone #define ENTRY_STRING(n, s) \ 96a33964b5SJonas Devlieghere { n, s, FormatEntity::Entry::Type::EscapeCode, 0, 0, nullptr, false } 97b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = { 9840dfc392SJonas Devlieghere ENTRY("*", ParentString)}; 99554f68d3SGreg Clayton 100b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = { 10140dfc392SJonas Devlieghere ENTRY("load", AddressLoad), 10240dfc392SJonas Devlieghere ENTRY("file", AddressFile), 10340dfc392SJonas Devlieghere ENTRY("load", AddressLoadOrFile), 104554f68d3SGreg Clayton }; 105554f68d3SGreg Clayton 106b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = { 10740dfc392SJonas Devlieghere ENTRY_VALUE("basename", ParentNumber, FileKind::Basename), 10840dfc392SJonas Devlieghere ENTRY_VALUE("dirname", ParentNumber, FileKind::Dirname), 10940dfc392SJonas Devlieghere ENTRY_VALUE("fullpath", ParentNumber, FileKind::Fullpath)}; 110554f68d3SGreg Clayton 111b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = { 11240dfc392SJonas Devlieghere ENTRY("index", FrameIndex), 11340dfc392SJonas Devlieghere ENTRY("pc", FrameRegisterPC), 11440dfc392SJonas Devlieghere ENTRY("fp", FrameRegisterFP), 11540dfc392SJonas Devlieghere ENTRY("sp", FrameRegisterSP), 11640dfc392SJonas Devlieghere ENTRY("flags", FrameRegisterFlags), 11740dfc392SJonas Devlieghere ENTRY("no-debug", FrameNoDebug), 11840dfc392SJonas Devlieghere ENTRY_CHILDREN("reg", FrameRegisterByName, g_string_entry), 11940dfc392SJonas Devlieghere ENTRY("is-artificial", FrameIsArtificial), 120554f68d3SGreg Clayton }; 121554f68d3SGreg Clayton 122b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = { 12340dfc392SJonas Devlieghere ENTRY("id", FunctionID), 12440dfc392SJonas Devlieghere ENTRY("name", FunctionName), 12540dfc392SJonas Devlieghere ENTRY("name-without-args", FunctionNameNoArgs), 12640dfc392SJonas Devlieghere ENTRY("name-with-args", FunctionNameWithArgs), 1277eaae939SMed Ismail Bennani ENTRY("mangled-name", FunctionMangledName), 12840dfc392SJonas Devlieghere ENTRY("addr-offset", FunctionAddrOffset), 12940dfc392SJonas Devlieghere ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete), 13040dfc392SJonas Devlieghere ENTRY("line-offset", FunctionLineOffset), 13140dfc392SJonas Devlieghere ENTRY("pc-offset", FunctionPCOffset), 13240dfc392SJonas Devlieghere ENTRY("initial-function", FunctionInitial), 13340dfc392SJonas Devlieghere ENTRY("changed", FunctionChanged), 13440dfc392SJonas Devlieghere ENTRY("is-optimized", FunctionIsOptimized)}; 135554f68d3SGreg Clayton 136b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = { 13740dfc392SJonas Devlieghere ENTRY_CHILDREN("file", LineEntryFile, g_file_child_entries), 13840dfc392SJonas Devlieghere ENTRY("number", LineEntryLineNumber), 13940dfc392SJonas Devlieghere ENTRY("column", LineEntryColumn), 14040dfc392SJonas Devlieghere ENTRY("start-addr", LineEntryStartAddress), 14140dfc392SJonas Devlieghere ENTRY("end-addr", LineEntryEndAddress), 142554f68d3SGreg Clayton }; 143554f68d3SGreg Clayton 144b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = { 14540dfc392SJonas Devlieghere ENTRY_CHILDREN("file", ModuleFile, g_file_child_entries), 146554f68d3SGreg Clayton }; 147554f68d3SGreg Clayton 148b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = { 14940dfc392SJonas Devlieghere ENTRY("id", ProcessID), 15040dfc392SJonas Devlieghere ENTRY_VALUE("name", ProcessFile, FileKind::Basename), 15140dfc392SJonas Devlieghere ENTRY_CHILDREN("file", ProcessFile, g_file_child_entries), 152554f68d3SGreg Clayton }; 153554f68d3SGreg Clayton 154b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = { 15540dfc392SJonas Devlieghere ENTRY("*", ParentString)}; 156554f68d3SGreg Clayton 157b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = { 15840dfc392SJonas Devlieghere ENTRY("*", ParentString)}; 159554f68d3SGreg Clayton 160b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = { 16140dfc392SJonas Devlieghere ENTRY("id", ThreadID), 16240dfc392SJonas Devlieghere ENTRY("protocol_id", ThreadProtocolID), 16340dfc392SJonas Devlieghere ENTRY("index", ThreadIndexID), 16440dfc392SJonas Devlieghere ENTRY_CHILDREN("info", ThreadInfo, g_string_entry), 16540dfc392SJonas Devlieghere ENTRY("queue", ThreadQueue), 16640dfc392SJonas Devlieghere ENTRY("name", ThreadName), 16740dfc392SJonas Devlieghere ENTRY("stop-reason", ThreadStopReason), 1687ebe9cc4SMed Ismail Bennani ENTRY("stop-reason-raw", ThreadStopReasonRaw), 16940dfc392SJonas Devlieghere ENTRY("return-value", ThreadReturnValue), 17040dfc392SJonas Devlieghere ENTRY("completed-expression", ThreadCompletedExpression), 171554f68d3SGreg Clayton }; 172554f68d3SGreg Clayton 173b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = { 17440dfc392SJonas Devlieghere ENTRY("arch", TargetArch), 175554f68d3SGreg Clayton }; 176554f68d3SGreg Clayton 177554f68d3SGreg Clayton #define _TO_STR2(_val) #_val 178554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val) 179554f68d3SGreg Clayton 180b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { 181b9c1b51eSKate Stone ENTRY_STRING("black", 182b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 183554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 184b9c1b51eSKate Stone ENTRY_STRING("green", 185b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 186b9c1b51eSKate Stone ENTRY_STRING("yellow", 187b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 188b9c1b51eSKate Stone ENTRY_STRING("blue", 189b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 190b9c1b51eSKate Stone ENTRY_STRING("purple", 191b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 192b9c1b51eSKate Stone ENTRY_STRING("cyan", 193b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 194b9c1b51eSKate Stone ENTRY_STRING("white", 195b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 196554f68d3SGreg Clayton }; 197554f68d3SGreg Clayton 198b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { 199b9c1b51eSKate Stone ENTRY_STRING("black", 200b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 201554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 202b9c1b51eSKate Stone ENTRY_STRING("green", 203b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 204b9c1b51eSKate Stone ENTRY_STRING("yellow", 205b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 206b9c1b51eSKate Stone ENTRY_STRING("blue", 207b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 208b9c1b51eSKate Stone ENTRY_STRING("purple", 209b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 210b9c1b51eSKate Stone ENTRY_STRING("cyan", 211b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 212b9c1b51eSKate Stone ENTRY_STRING("white", 213b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 214554f68d3SGreg Clayton }; 215554f68d3SGreg Clayton 216b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = { 21740dfc392SJonas Devlieghere ENTRY_CHILDREN("fg", Invalid, g_ansi_fg_entries), 21840dfc392SJonas Devlieghere ENTRY_CHILDREN("bg", Invalid, g_ansi_bg_entries), 219b9c1b51eSKate Stone ENTRY_STRING("normal", 220b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 221554f68d3SGreg Clayton ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 222554f68d3SGreg Clayton ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 223b9c1b51eSKate Stone ENTRY_STRING("italic", 224b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 225b9c1b51eSKate Stone ENTRY_STRING("underline", 226b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 227b9c1b51eSKate Stone ENTRY_STRING("slow-blink", 228b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 229b9c1b51eSKate Stone ENTRY_STRING("fast-blink", 230b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 231b9c1b51eSKate Stone ENTRY_STRING("negative", 232b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 233b9c1b51eSKate Stone ENTRY_STRING("conceal", 234b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 235b9c1b51eSKate Stone ENTRY_STRING("crossed-out", 236b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 237554f68d3SGreg Clayton }; 238554f68d3SGreg Clayton 239b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = { 24040dfc392SJonas Devlieghere ENTRY("frame", ScriptFrame), ENTRY("process", ScriptProcess), 24140dfc392SJonas Devlieghere ENTRY("target", ScriptTarget), ENTRY("thread", ScriptThread), 24240dfc392SJonas Devlieghere ENTRY("var", ScriptVariable), ENTRY("svar", ScriptVariableSynthetic), 24340dfc392SJonas Devlieghere ENTRY("thread", ScriptThread), 244554f68d3SGreg Clayton }; 245554f68d3SGreg Clayton 246b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = { 24740dfc392SJonas Devlieghere ENTRY_CHILDREN("addr", AddressLoadOrFile, g_addr_entries), 24840dfc392SJonas Devlieghere ENTRY("addr-file-or-load", AddressLoadOrFile), 24940dfc392SJonas Devlieghere ENTRY_CHILDREN("ansi", Invalid, g_ansi_entries), 25040dfc392SJonas Devlieghere ENTRY("current-pc-arrow", CurrentPCArrow), 25140dfc392SJonas Devlieghere ENTRY_CHILDREN("file", File, g_file_child_entries), 25240dfc392SJonas Devlieghere ENTRY("language", Lang), 25340dfc392SJonas Devlieghere ENTRY_CHILDREN("frame", Invalid, g_frame_child_entries), 25440dfc392SJonas Devlieghere ENTRY_CHILDREN("function", Invalid, g_function_child_entries), 25540dfc392SJonas Devlieghere ENTRY_CHILDREN("line", Invalid, g_line_child_entries), 25640dfc392SJonas Devlieghere ENTRY_CHILDREN("module", Invalid, g_module_child_entries), 25740dfc392SJonas Devlieghere ENTRY_CHILDREN("process", Invalid, g_process_child_entries), 25840dfc392SJonas Devlieghere ENTRY_CHILDREN("script", Invalid, g_script_child_entries), 25940dfc392SJonas Devlieghere ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, g_svar_child_entries), 26040dfc392SJonas Devlieghere ENTRY_CHILDREN("thread", Invalid, g_thread_child_entries), 26140dfc392SJonas Devlieghere ENTRY_CHILDREN("target", Invalid, g_target_child_entries), 26240dfc392SJonas Devlieghere ENTRY_CHILDREN_KEEP_SEP("var", Variable, g_var_child_entries), 263554f68d3SGreg Clayton }; 264554f68d3SGreg Clayton 265b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root = 26640dfc392SJonas Devlieghere ENTRY_CHILDREN("<root>", Root, g_top_level_entries); 267554f68d3SGreg Clayton 268b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s) 269b9c1b51eSKate Stone : string(s.data(), s.size()), printf_format(), children(), 270b9c1b51eSKate Stone definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), 271b9c1b51eSKate Stone number(0), deref(false) {} 272554f68d3SGreg Clayton 273b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch) 274b9c1b51eSKate Stone : string(1, ch), printf_format(), children(), definition(nullptr), 275b9c1b51eSKate Stone type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} 276554f68d3SGreg Clayton 277b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) { 278554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 279554f68d3SGreg Clayton children.push_back(Entry(ch)); 280554f68d3SGreg Clayton else 281554f68d3SGreg Clayton children.back().string.append(1, ch); 282554f68d3SGreg Clayton } 283554f68d3SGreg Clayton 284b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { 285554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 286554f68d3SGreg Clayton children.push_back(Entry(s)); 287554f68d3SGreg Clayton else 288554f68d3SGreg Clayton children.back().string.append(s.data(), s.size()); 289554f68d3SGreg Clayton } 290554f68d3SGreg Clayton 291b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) { 292554f68d3SGreg Clayton return AppendText(llvm::StringRef(cstr)); 293554f68d3SGreg Clayton } 294554f68d3SGreg Clayton 29597206d57SZachary Turner Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { 296554f68d3SGreg Clayton entry.Clear(); 297554f68d3SGreg Clayton entry.type = Entry::Type::Root; 298554f68d3SGreg Clayton llvm::StringRef modifiable_format(format_str); 299554f68d3SGreg Clayton return ParseInternal(modifiable_format, entry, 0); 300554f68d3SGreg Clayton } 301554f68d3SGreg Clayton 302b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee) \ 303b9c1b51eSKate Stone case FormatEntity::Entry::Type::eee: \ 304b9c1b51eSKate Stone return #eee 305554f68d3SGreg Clayton 306b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) { 307b9c1b51eSKate Stone switch (t) { 308554f68d3SGreg Clayton ENUM_TO_CSTR(Invalid); 309554f68d3SGreg Clayton ENUM_TO_CSTR(ParentNumber); 310554f68d3SGreg Clayton ENUM_TO_CSTR(ParentString); 311a33964b5SJonas Devlieghere ENUM_TO_CSTR(EscapeCode); 312554f68d3SGreg Clayton ENUM_TO_CSTR(Root); 313554f68d3SGreg Clayton ENUM_TO_CSTR(String); 314554f68d3SGreg Clayton ENUM_TO_CSTR(Scope); 315554f68d3SGreg Clayton ENUM_TO_CSTR(Variable); 316554f68d3SGreg Clayton ENUM_TO_CSTR(VariableSynthetic); 317554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariable); 318554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariableSynthetic); 319554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoad); 320554f68d3SGreg Clayton ENUM_TO_CSTR(AddressFile); 321554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoadOrFile); 322554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessID); 323554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessFile); 324554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptProcess); 325554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadID); 326554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadProtocolID); 327554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadIndexID); 328554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadName); 329554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadQueue); 330554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadStopReason); 3317ebe9cc4SMed Ismail Bennani ENUM_TO_CSTR(ThreadStopReasonRaw); 332554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadReturnValue); 333554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadCompletedExpression); 334554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptThread); 335554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadInfo); 336554f68d3SGreg Clayton ENUM_TO_CSTR(TargetArch); 337554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptTarget); 338554f68d3SGreg Clayton ENUM_TO_CSTR(ModuleFile); 339554f68d3SGreg Clayton ENUM_TO_CSTR(File); 340dc975670SDawn Perchik ENUM_TO_CSTR(Lang); 341554f68d3SGreg Clayton ENUM_TO_CSTR(FrameIndex); 3426a9767c7SJim Ingham ENUM_TO_CSTR(FrameNoDebug); 343554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterPC); 344554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterSP); 345554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFP); 346554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFlags); 347554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterByName); 3484b36f791SVedant Kumar ENUM_TO_CSTR(FrameIsArtificial); 349554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptFrame); 350554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionID); 351554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionDidChange); 352554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionInitialFunction); 353554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionName); 354554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameWithArgs); 355554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameNoArgs); 3567eaae939SMed Ismail Bennani ENUM_TO_CSTR(FunctionMangledName); 357554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffset); 358554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 359554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionLineOffset); 360554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionPCOffset); 361c980fa92SJason Molenda ENUM_TO_CSTR(FunctionInitial); 362c980fa92SJason Molenda ENUM_TO_CSTR(FunctionChanged); 3636ab659a9SJason Molenda ENUM_TO_CSTR(FunctionIsOptimized); 364554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryFile); 365554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryLineNumber); 3664954f6a5SAdrian Prantl ENUM_TO_CSTR(LineEntryColumn); 367554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryStartAddress); 368554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryEndAddress); 369554f68d3SGreg Clayton ENUM_TO_CSTR(CurrentPCArrow); 370554f68d3SGreg Clayton } 371554f68d3SGreg Clayton return "???"; 372554f68d3SGreg Clayton } 373554f68d3SGreg Clayton 374554f68d3SGreg Clayton #undef ENUM_TO_CSTR 375554f68d3SGreg Clayton 376b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const { 377554f68d3SGreg Clayton s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 378554f68d3SGreg Clayton if (fmt != eFormatDefault) 379554f68d3SGreg Clayton s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); 380554f68d3SGreg Clayton if (!string.empty()) 381554f68d3SGreg Clayton s.Printf("string = \"%s\"", string.c_str()); 382554f68d3SGreg Clayton if (!printf_format.empty()) 383554f68d3SGreg Clayton s.Printf("printf_format = \"%s\"", printf_format.c_str()); 384554f68d3SGreg Clayton if (number != 0) 385554f68d3SGreg Clayton s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 386554f68d3SGreg Clayton if (deref) 387554f68d3SGreg Clayton s.Printf("deref = true, "); 388554f68d3SGreg Clayton s.EOL(); 389b9c1b51eSKate Stone for (const auto &child : children) { 390554f68d3SGreg Clayton child.Dump(s, depth + 1); 391554f68d3SGreg Clayton } 392554f68d3SGreg Clayton } 393554f68d3SGreg Clayton 394554f68d3SGreg Clayton template <typename T> 395b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, 396b9c1b51eSKate Stone const ExecutionContext *exe_ctx, T t, 397b9c1b51eSKate Stone const char *script_function_name) { 398554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 399554f68d3SGreg Clayton 400b9c1b51eSKate Stone if (target) { 401b9c1b51eSKate Stone ScriptInterpreter *script_interpreter = 4022b29b432SJonas Devlieghere target->GetDebugger().GetScriptInterpreter(); 403b9c1b51eSKate Stone if (script_interpreter) { 40497206d57SZachary Turner Status error; 405554f68d3SGreg Clayton std::string script_output; 406554f68d3SGreg Clayton 407b9c1b51eSKate Stone if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, 408b9c1b51eSKate Stone script_output, error) && 409b9c1b51eSKate Stone error.Success()) { 410554f68d3SGreg Clayton s.Printf("%s", script_output.c_str()); 411554f68d3SGreg Clayton return true; 412b9c1b51eSKate Stone } else { 413554f68d3SGreg Clayton s.Printf("<error: %s>", error.AsCString()); 414554f68d3SGreg Clayton } 415554f68d3SGreg Clayton } 416554f68d3SGreg Clayton } 417554f68d3SGreg Clayton return false; 418554f68d3SGreg Clayton } 419554f68d3SGreg Clayton 4201462f5a4SRaphael Isemann static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc, 4211462f5a4SRaphael Isemann const ExecutionContext *exe_ctx, 4221462f5a4SRaphael Isemann const Address &addr, 423b9c1b51eSKate Stone bool print_file_addr_or_load_addr) { 424554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 425554f68d3SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 426554f68d3SGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 427554f68d3SGreg Clayton vaddr = addr.GetLoadAddress(target); 428554f68d3SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 429554f68d3SGreg Clayton vaddr = addr.GetFileAddress(); 430554f68d3SGreg Clayton 431b9c1b51eSKate Stone if (vaddr != LLDB_INVALID_ADDRESS) { 432554f68d3SGreg Clayton int addr_width = 0; 433b9c1b51eSKate Stone if (exe_ctx && target) { 434554f68d3SGreg Clayton addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 435554f68d3SGreg Clayton } 436554f68d3SGreg Clayton if (addr_width == 0) 437554f68d3SGreg Clayton addr_width = 16; 438b9c1b51eSKate Stone if (print_file_addr_or_load_addr) { 439a74f37a5SEugene Zelenko ExecutionContextScope *exe_scope = nullptr; 440554f68d3SGreg Clayton if (exe_ctx) 441554f68d3SGreg Clayton exe_scope = exe_ctx->GetBestExecutionContextScope(); 442b9c1b51eSKate Stone addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, 443b9c1b51eSKate Stone Address::DumpStyleModuleWithFileAddress, 0); 444b9c1b51eSKate Stone } else { 445554f68d3SGreg Clayton s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 446554f68d3SGreg Clayton } 447554f68d3SGreg Clayton return true; 448554f68d3SGreg Clayton } 449554f68d3SGreg Clayton return false; 450554f68d3SGreg Clayton } 451554f68d3SGreg Clayton 452b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, 453554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 454554f68d3SGreg Clayton const Address &format_addr, 455b9c1b51eSKate Stone bool concrete_only, bool no_padding, 456b9c1b51eSKate Stone bool print_zero_offsets) { 457b9c1b51eSKate Stone if (format_addr.IsValid()) { 458554f68d3SGreg Clayton Address func_addr; 459554f68d3SGreg Clayton 460b9c1b51eSKate Stone if (sc) { 461b9c1b51eSKate Stone if (sc->function) { 462554f68d3SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 463b9c1b51eSKate Stone if (sc->block && !concrete_only) { 46405097246SAdrian Prantl // Check to make sure we aren't in an inline function. If we are, use 46505097246SAdrian Prantl // the inline block range that contains "format_addr" since blocks 46605097246SAdrian Prantl // can be discontiguous. 467554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 468554f68d3SGreg Clayton AddressRange inline_range; 46940dfc392SJonas Devlieghere if (inline_block && inline_block->GetRangeContainingAddress( 47040dfc392SJonas Devlieghere format_addr, inline_range)) 471554f68d3SGreg Clayton func_addr = inline_range.GetBaseAddress(); 472554f68d3SGreg Clayton } 473b9c1b51eSKate Stone } else if (sc->symbol && sc->symbol->ValueIsAddress()) 474358cf1eaSGreg Clayton func_addr = sc->symbol->GetAddressRef(); 475554f68d3SGreg Clayton } 476554f68d3SGreg Clayton 477b9c1b51eSKate Stone if (func_addr.IsValid()) { 478554f68d3SGreg Clayton const char *addr_offset_padding = no_padding ? "" : " "; 479554f68d3SGreg Clayton 480b9c1b51eSKate Stone if (func_addr.GetSection() == format_addr.GetSection()) { 481554f68d3SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 482554f68d3SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 483b9c1b51eSKate Stone if (addr_file_addr > func_file_addr || 484b9c1b51eSKate Stone (addr_file_addr == func_file_addr && print_zero_offsets)) { 485b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 486b9c1b51eSKate Stone addr_file_addr - func_file_addr); 487b9c1b51eSKate Stone } else if (addr_file_addr < func_file_addr) { 488b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 489b9c1b51eSKate Stone func_file_addr - addr_file_addr); 490c980fa92SJason Molenda } 491554f68d3SGreg Clayton return true; 492b9c1b51eSKate Stone } else { 493554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 494b9c1b51eSKate Stone if (target) { 495554f68d3SGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress(target); 496554f68d3SGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress(target); 497b9c1b51eSKate Stone if (addr_load_addr > func_load_addr || 498b9c1b51eSKate Stone (addr_load_addr == func_load_addr && print_zero_offsets)) { 499b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 500b9c1b51eSKate Stone addr_load_addr - func_load_addr); 501b9c1b51eSKate Stone } else if (addr_load_addr < func_load_addr) { 502b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 503b9c1b51eSKate Stone func_load_addr - addr_load_addr); 504c980fa92SJason Molenda } 505554f68d3SGreg Clayton return true; 506554f68d3SGreg Clayton } 507554f68d3SGreg Clayton } 508554f68d3SGreg Clayton } 509554f68d3SGreg Clayton } 510554f68d3SGreg Clayton return false; 511554f68d3SGreg Clayton } 512554f68d3SGreg Clayton 513b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath, 514554f68d3SGreg Clayton size_t &close_bracket_index, 515554f68d3SGreg Clayton const char *&var_name_final_if_array_range, 516b9c1b51eSKate Stone int64_t &index_lower, int64_t &index_higher) { 5174edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 518554f68d3SGreg Clayton close_bracket_index = llvm::StringRef::npos; 519554f68d3SGreg Clayton const size_t open_bracket_index = subpath.find('['); 520b9c1b51eSKate Stone if (open_bracket_index == llvm::StringRef::npos) { 52163e5fb76SJonas Devlieghere LLDB_LOGF(log, 52263e5fb76SJonas Devlieghere "[ScanBracketedRange] no bracketed range, skipping entirely"); 523554f68d3SGreg Clayton return false; 524554f68d3SGreg Clayton } 525554f68d3SGreg Clayton 526554f68d3SGreg Clayton close_bracket_index = subpath.find(']', open_bracket_index + 1); 527554f68d3SGreg Clayton 528b9c1b51eSKate Stone if (close_bracket_index == llvm::StringRef::npos) { 52963e5fb76SJonas Devlieghere LLDB_LOGF(log, 53063e5fb76SJonas Devlieghere "[ScanBracketedRange] no bracketed range, skipping entirely"); 531554f68d3SGreg Clayton return false; 532b9c1b51eSKate Stone } else { 533554f68d3SGreg Clayton var_name_final_if_array_range = subpath.data() + open_bracket_index; 534554f68d3SGreg Clayton 535b9c1b51eSKate Stone if (close_bracket_index - open_bracket_index == 1) { 53663e5fb76SJonas Devlieghere LLDB_LOGF( 53763e5fb76SJonas Devlieghere log, 538b9c1b51eSKate Stone "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 539554f68d3SGreg Clayton index_lower = 0; 540b9c1b51eSKate Stone } else { 541554f68d3SGreg Clayton const size_t separator_index = subpath.find('-', open_bracket_index + 1); 542554f68d3SGreg Clayton 543b9c1b51eSKate Stone if (separator_index == llvm::StringRef::npos) { 544554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 545a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 546554f68d3SGreg Clayton index_higher = index_lower; 54763e5fb76SJonas Devlieghere LLDB_LOGF(log, 54863e5fb76SJonas Devlieghere "[ScanBracketedRange] [%" PRId64 549b9c1b51eSKate Stone "] detected, high index is same", 550b9c1b51eSKate Stone index_lower); 551b9c1b51eSKate Stone } else { 552554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 553554f68d3SGreg Clayton const char *index_higher_cstr = subpath.data() + separator_index + 1; 554a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 555a74f37a5SEugene Zelenko index_higher = ::strtoul(index_higher_cstr, nullptr, 0); 55663e5fb76SJonas Devlieghere LLDB_LOGF(log, 55763e5fb76SJonas Devlieghere "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", 558b9c1b51eSKate Stone index_lower, index_higher); 559554f68d3SGreg Clayton } 560b9c1b51eSKate Stone if (index_lower > index_higher && index_higher > 0) { 56163e5fb76SJonas Devlieghere LLDB_LOGF(log, "[ScanBracketedRange] swapping indices"); 562554f68d3SGreg Clayton const int64_t temp = index_lower; 563554f68d3SGreg Clayton index_lower = index_higher; 564554f68d3SGreg Clayton index_higher = temp; 565554f68d3SGreg Clayton } 566554f68d3SGreg Clayton } 567554f68d3SGreg Clayton } 568554f68d3SGreg Clayton return true; 569554f68d3SGreg Clayton } 570554f68d3SGreg Clayton 571b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { 572b9c1b51eSKate Stone switch (file_kind) { 573554f68d3SGreg Clayton case FileKind::FileError: 574554f68d3SGreg Clayton break; 575554f68d3SGreg Clayton 576554f68d3SGreg Clayton case FileKind::Basename: 577b9c1b51eSKate Stone if (file.GetFilename()) { 578554f68d3SGreg Clayton s << file.GetFilename(); 579554f68d3SGreg Clayton return true; 580554f68d3SGreg Clayton } 581554f68d3SGreg Clayton break; 582554f68d3SGreg Clayton 583554f68d3SGreg Clayton case FileKind::Dirname: 584b9c1b51eSKate Stone if (file.GetDirectory()) { 585554f68d3SGreg Clayton s << file.GetDirectory(); 586554f68d3SGreg Clayton return true; 587554f68d3SGreg Clayton } 588554f68d3SGreg Clayton break; 589554f68d3SGreg Clayton 590554f68d3SGreg Clayton case FileKind::Fullpath: 591b9c1b51eSKate Stone if (file) { 592554f68d3SGreg Clayton s << file; 593554f68d3SGreg Clayton return true; 594554f68d3SGreg Clayton } 595554f68d3SGreg Clayton break; 596554f68d3SGreg Clayton } 597554f68d3SGreg Clayton return false; 598554f68d3SGreg Clayton } 599554f68d3SGreg Clayton 600b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, 601b9c1b51eSKate Stone uint32_t reg_num, Format format) 602554f68d3SGreg Clayton 603554f68d3SGreg Clayton { 604b9c1b51eSKate Stone if (frame) { 605554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 606554f68d3SGreg Clayton 607b9c1b51eSKate Stone if (reg_ctx) { 608b9c1b51eSKate Stone const uint32_t lldb_reg_num = 609b9c1b51eSKate Stone reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 610b9c1b51eSKate Stone if (lldb_reg_num != LLDB_INVALID_REGNUM) { 611b9c1b51eSKate Stone const RegisterInfo *reg_info = 612b9c1b51eSKate Stone reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); 613b9c1b51eSKate Stone if (reg_info) { 614554f68d3SGreg Clayton RegisterValue reg_value; 615b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 616e03334cfSPavel Labath DumpRegisterValue(reg_value, &s, reg_info, false, false, format); 617554f68d3SGreg Clayton return true; 618554f68d3SGreg Clayton } 619554f68d3SGreg Clayton } 620554f68d3SGreg Clayton } 621554f68d3SGreg Clayton } 622554f68d3SGreg Clayton } 623554f68d3SGreg Clayton return false; 624554f68d3SGreg Clayton } 625554f68d3SGreg Clayton 626b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, 627554f68d3SGreg Clayton StackFrame *frame, 628b9c1b51eSKate Stone bool deref_pointer) { 6294edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 630554f68d3SGreg Clayton const char *ptr_deref_format = "[%d]"; 631554f68d3SGreg Clayton std::string ptr_deref_buffer(10, 0); 632554f68d3SGreg Clayton ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 63363e5fb76SJonas Devlieghere LLDB_LOGF(log, "[ExpandIndexedExpression] name to deref: %s", 634b9c1b51eSKate Stone ptr_deref_buffer.c_str()); 635554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 636554f68d3SGreg Clayton ValueObject::ExpressionPathEndResultType final_value_type; 637554f68d3SGreg Clayton ValueObject::ExpressionPathScanEndReason reason_to_stop; 638b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 639b9c1b51eSKate Stone (deref_pointer ? ValueObject::eExpressionPathAftermathDereference 640b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 641b9c1b51eSKate Stone ValueObjectSP item = valobj->GetValueForExpressionPath( 642d2daca77SZachary Turner ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, 643d2daca77SZachary Turner &what_next); 644b9c1b51eSKate Stone if (!item) { 64563e5fb76SJonas Devlieghere LLDB_LOGF(log, 64663e5fb76SJonas Devlieghere "[ExpandIndexedExpression] ERROR: why stopping = %d," 647554f68d3SGreg Clayton " final_value_type %d", 648d2daca77SZachary Turner reason_to_stop, final_value_type); 649b9c1b51eSKate Stone } else { 65063e5fb76SJonas Devlieghere LLDB_LOGF(log, 65163e5fb76SJonas Devlieghere "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," 652554f68d3SGreg Clayton " final_value_type %d", 653d2daca77SZachary Turner reason_to_stop, final_value_type); 654554f68d3SGreg Clayton } 655554f68d3SGreg Clayton return item; 656554f68d3SGreg Clayton } 657554f68d3SGreg Clayton 658b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar( 659b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle style) { 660b9c1b51eSKate Stone switch (style) { 661b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: 662b9c1b51eSKate Stone return '@'; 663b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleValue: 664b9c1b51eSKate Stone return 'V'; 665b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLocation: 666b9c1b51eSKate Stone return 'L'; 667b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleSummary: 668b9c1b51eSKate Stone return 'S'; 669b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleChildrenCount: 670b9c1b51eSKate Stone return '#'; 671b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleType: 672b9c1b51eSKate Stone return 'T'; 673b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleName: 674b9c1b51eSKate Stone return 'N'; 675b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleExpressionPath: 676b9c1b51eSKate Stone return '>'; 677554f68d3SGreg Clayton } 678554f68d3SGreg Clayton return '\0'; 679554f68d3SGreg Clayton } 680554f68d3SGreg Clayton 681b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc, 682554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 683b9c1b51eSKate Stone const FormatEntity::Entry &entry, ValueObject *valobj) { 684a74f37a5SEugene Zelenko if (valobj == nullptr) 685554f68d3SGreg Clayton return false; 686554f68d3SGreg Clayton 6874edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 688554f68d3SGreg Clayton Format custom_format = eFormatInvalid; 689b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle val_obj_display = 690b9c1b51eSKate Stone entry.string.empty() 691b9c1b51eSKate Stone ? ValueObject::eValueObjectRepresentationStyleValue 692b9c1b51eSKate Stone : ValueObject::eValueObjectRepresentationStyleSummary; 693554f68d3SGreg Clayton 694554f68d3SGreg Clayton bool do_deref_pointer = entry.deref; 695554f68d3SGreg Clayton bool is_script = false; 696b9c1b51eSKate Stone switch (entry.type) { 697554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariable: 698554f68d3SGreg Clayton is_script = true; 699554f68d3SGreg Clayton break; 700554f68d3SGreg Clayton 701554f68d3SGreg Clayton case FormatEntity::Entry::Type::Variable: 702554f68d3SGreg Clayton custom_format = entry.fmt; 703554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 704554f68d3SGreg Clayton break; 705554f68d3SGreg Clayton 706554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariableSynthetic: 707554f68d3SGreg Clayton is_script = true; 70862e0681aSJason Molenda LLVM_FALLTHROUGH; 709554f68d3SGreg Clayton case FormatEntity::Entry::Type::VariableSynthetic: 710554f68d3SGreg Clayton custom_format = entry.fmt; 711554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 712b9c1b51eSKate Stone if (!valobj->IsSynthetic()) { 713554f68d3SGreg Clayton valobj = valobj->GetSyntheticValue().get(); 714554f68d3SGreg Clayton if (valobj == nullptr) 715554f68d3SGreg Clayton return false; 716554f68d3SGreg Clayton } 717554f68d3SGreg Clayton break; 718554f68d3SGreg Clayton 719554f68d3SGreg Clayton default: 720554f68d3SGreg Clayton return false; 721554f68d3SGreg Clayton } 722554f68d3SGreg Clayton 723a74f37a5SEugene Zelenko if (valobj == nullptr) 724554f68d3SGreg Clayton return false; 725554f68d3SGreg Clayton 726b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 727b9c1b51eSKate Stone (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference 728b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 729554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 730b9c1b51eSKate Stone options.DontCheckDotVsArrowSyntax() 731b9c1b51eSKate Stone .DoAllowBitfieldSyntax() 732b9c1b51eSKate Stone .DoAllowFragileIVar() 733b9c1b51eSKate Stone .SetSyntheticChildrenTraversal( 734b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions:: 735b9c1b51eSKate Stone SyntheticChildrenTraversal::Both); 736a74f37a5SEugene Zelenko ValueObject *target = nullptr; 737a74f37a5SEugene Zelenko const char *var_name_final_if_array_range = nullptr; 738554f68d3SGreg Clayton size_t close_bracket_index = llvm::StringRef::npos; 739554f68d3SGreg Clayton int64_t index_lower = -1; 740554f68d3SGreg Clayton int64_t index_higher = -1; 741554f68d3SGreg Clayton bool is_array_range = false; 742554f68d3SGreg Clayton bool was_plain_var = false; 743554f68d3SGreg Clayton bool was_var_format = false; 744554f68d3SGreg Clayton bool was_var_indexed = false; 745b9c1b51eSKate Stone ValueObject::ExpressionPathScanEndReason reason_to_stop = 746b9c1b51eSKate Stone ValueObject::eExpressionPathScanEndReasonEndOfString; 747b9c1b51eSKate Stone ValueObject::ExpressionPathEndResultType final_value_type = 748b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypePlain; 749554f68d3SGreg Clayton 750b9c1b51eSKate Stone if (is_script) { 751554f68d3SGreg Clayton return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); 752554f68d3SGreg Clayton } 753554f68d3SGreg Clayton 754554f68d3SGreg Clayton llvm::StringRef subpath(entry.string); 755554f68d3SGreg Clayton // simplest case ${var}, just print valobj's value 756b9c1b51eSKate Stone if (entry.string.empty()) { 757b9c1b51eSKate Stone if (entry.printf_format.empty() && entry.fmt == eFormatDefault && 758b9c1b51eSKate Stone entry.number == ValueObject::eValueObjectRepresentationStyleValue) 759554f68d3SGreg Clayton was_plain_var = true; 760554f68d3SGreg Clayton else 761554f68d3SGreg Clayton was_var_format = true; 762554f68d3SGreg Clayton target = valobj; 763b9c1b51eSKate Stone } else // this is ${var.something} or multiple .something nested 764554f68d3SGreg Clayton { 765554f68d3SGreg Clayton if (entry.string[0] == '[') 766554f68d3SGreg Clayton was_var_indexed = true; 767b9c1b51eSKate Stone ScanBracketedRange(subpath, close_bracket_index, 768b9c1b51eSKate Stone var_name_final_if_array_range, index_lower, 769554f68d3SGreg Clayton index_higher); 770554f68d3SGreg Clayton 77197206d57SZachary Turner Status error; 772554f68d3SGreg Clayton 773554f68d3SGreg Clayton const std::string &expr_path = entry.string; 774554f68d3SGreg Clayton 77563e5fb76SJonas Devlieghere LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s", 776b9c1b51eSKate Stone expr_path.c_str()); 777554f68d3SGreg Clayton 778d2daca77SZachary Turner target = 779d2daca77SZachary Turner valobj 780d2daca77SZachary Turner ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, 781d2daca77SZachary Turner &final_value_type, options, &what_next) 782b9c1b51eSKate Stone .get(); 783554f68d3SGreg Clayton 784b9c1b51eSKate Stone if (!target) { 78563e5fb76SJonas Devlieghere LLDB_LOGF(log, 78663e5fb76SJonas Devlieghere "[Debugger::FormatPrompt] ERROR: why stopping = %d," 787655c4525SZachary Turner " final_value_type %d", 788d2daca77SZachary Turner reason_to_stop, final_value_type); 789554f68d3SGreg Clayton return false; 790b9c1b51eSKate Stone } else { 79163e5fb76SJonas Devlieghere LLDB_LOGF(log, 79263e5fb76SJonas Devlieghere "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," 793655c4525SZachary Turner " final_value_type %d", 794d2daca77SZachary Turner reason_to_stop, final_value_type); 795b9c1b51eSKate Stone target = target 796b9c1b51eSKate Stone ->GetQualifiedRepresentationIfAvailable( 797b9c1b51eSKate Stone target->GetDynamicValueType(), true) 798b9c1b51eSKate Stone .get(); 799554f68d3SGreg Clayton } 800554f68d3SGreg Clayton } 801554f68d3SGreg Clayton 802b9c1b51eSKate Stone is_array_range = 803b9c1b51eSKate Stone (final_value_type == 804b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeBoundedRange || 805b9c1b51eSKate Stone final_value_type == 806b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeUnboundedRange); 807554f68d3SGreg Clayton 808b9c1b51eSKate Stone do_deref_pointer = 809b9c1b51eSKate Stone (what_next == ValueObject::eExpressionPathAftermathDereference); 810554f68d3SGreg Clayton 811b9c1b51eSKate Stone if (do_deref_pointer && !is_array_range) { 812554f68d3SGreg Clayton // I have not deref-ed yet, let's do it 813b9c1b51eSKate Stone // this happens when we are not going through 81405097246SAdrian Prantl // GetValueForVariableExpressionPath to get to the target ValueObject 81597206d57SZachary Turner Status error; 816554f68d3SGreg Clayton target = target->Dereference(error).get(); 817b9c1b51eSKate Stone if (error.Fail()) { 81863e5fb76SJonas Devlieghere LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n", 819b9c1b51eSKate Stone error.AsCString("unknown")); 820554f68d3SGreg Clayton return false; 821554f68d3SGreg Clayton } 822554f68d3SGreg Clayton do_deref_pointer = false; 823554f68d3SGreg Clayton } 824554f68d3SGreg Clayton 825b9c1b51eSKate Stone if (!target) { 82663e5fb76SJonas Devlieghere LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for " 827b9c1b51eSKate Stone "prompt expression"); 828554f68d3SGreg Clayton return false; 829554f68d3SGreg Clayton } 830554f68d3SGreg Clayton 83105097246SAdrian Prantl // we do not want to use the summary for a bitfield of type T:n if we were 83205097246SAdrian Prantl // originally dealing with just a T - that would get us into an endless 83305097246SAdrian Prantl // recursion 834b9c1b51eSKate Stone if (target->IsBitfield() && was_var_indexed) { 835554f68d3SGreg Clayton // TODO: check for a (T:n)-specific summary - we should still obey that 836554f68d3SGreg Clayton StreamString bitfield_name; 837b9c1b51eSKate Stone bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), 838b9c1b51eSKate Stone target->GetBitfieldBitSize()); 8392f3df613SZachary Turner auto type_sp = std::make_shared<TypeNameSpecifierImpl>( 8402f3df613SZachary Turner bitfield_name.GetString(), false); 841b9c1b51eSKate Stone if (val_obj_display == 842b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary && 843b9c1b51eSKate Stone !DataVisualization::GetSummaryForType(type_sp)) 844554f68d3SGreg Clayton val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 845554f68d3SGreg Clayton } 846554f68d3SGreg Clayton 847554f68d3SGreg Clayton // TODO use flags for these 848b9c1b51eSKate Stone const uint32_t type_info_flags = 849b9c1b51eSKate Stone target->GetCompilerType().GetTypeInfo(nullptr); 850554f68d3SGreg Clayton bool is_array = (type_info_flags & eTypeIsArray) != 0; 851554f68d3SGreg Clayton bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 85299558cc4SGreg Clayton bool is_aggregate = target->GetCompilerType().IsAggregateType(); 853554f68d3SGreg Clayton 854b9c1b51eSKate Stone if ((is_array || is_pointer) && (!is_array_range) && 855b9c1b51eSKate Stone val_obj_display == 856b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue) // this should be 857b9c1b51eSKate Stone // wrong, but there 858b9c1b51eSKate Stone // are some 859b9c1b51eSKate Stone // exceptions 860554f68d3SGreg Clayton { 861554f68d3SGreg Clayton StreamString str_temp; 86263e5fb76SJonas Devlieghere LLDB_LOGF(log, 863b9c1b51eSKate Stone "[Debugger::FormatPrompt] I am into array || pointer && !range"); 864554f68d3SGreg Clayton 865b9c1b51eSKate Stone if (target->HasSpecialPrintableRepresentation(val_obj_display, 866b9c1b51eSKate Stone custom_format)) { 867554f68d3SGreg Clayton // try to use the special cases 868b9c1b51eSKate Stone bool success = target->DumpPrintableRepresentation( 869b9c1b51eSKate Stone str_temp, val_obj_display, custom_format); 87063e5fb76SJonas Devlieghere LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match", 871b9c1b51eSKate Stone success ? "" : "n't"); 872554f68d3SGreg Clayton 873554f68d3SGreg Clayton // should not happen 874554f68d3SGreg Clayton if (success) 875c156427dSZachary Turner s << str_temp.GetString(); 876554f68d3SGreg Clayton return true; 877b9c1b51eSKate Stone } else { 878554f68d3SGreg Clayton if (was_plain_var) // if ${var} 879554f68d3SGreg Clayton { 880554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 881b9c1b51eSKate Stone } else if (is_pointer) // if pointer, value is the address stored 882554f68d3SGreg Clayton { 883b9c1b51eSKate Stone target->DumpPrintableRepresentation( 884b9c1b51eSKate Stone s, val_obj_display, custom_format, 88565d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable); 886554f68d3SGreg Clayton } 887554f68d3SGreg Clayton return true; 888554f68d3SGreg Clayton } 889554f68d3SGreg Clayton } 890554f68d3SGreg Clayton 891b9c1b51eSKate Stone // if directly trying to print ${var}, and this is an aggregate, display a 89205097246SAdrian Prantl // nice type @ location message 893b9c1b51eSKate Stone if (is_aggregate && was_plain_var) { 894554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 895554f68d3SGreg Clayton return true; 896554f68d3SGreg Clayton } 897554f68d3SGreg Clayton 898b9c1b51eSKate Stone // if directly trying to print ${var%V}, and this is an aggregate, do not let 899b9c1b51eSKate Stone // the user do it 900b9c1b51eSKate Stone if (is_aggregate && 901b9c1b51eSKate Stone ((was_var_format && 902b9c1b51eSKate Stone val_obj_display == 903b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue))) { 904554f68d3SGreg Clayton s << "<invalid use of aggregate type>"; 905554f68d3SGreg Clayton return true; 906554f68d3SGreg Clayton } 907554f68d3SGreg Clayton 908b9c1b51eSKate Stone if (!is_array_range) { 90963e5fb76SJonas Devlieghere LLDB_LOGF(log, 91063e5fb76SJonas Devlieghere "[Debugger::FormatPrompt] dumping ordinary printable output"); 911b9c1b51eSKate Stone return target->DumpPrintableRepresentation(s, val_obj_display, 912b9c1b51eSKate Stone custom_format); 913b9c1b51eSKate Stone } else { 91463e5fb76SJonas Devlieghere LLDB_LOGF(log, 91563e5fb76SJonas Devlieghere "[Debugger::FormatPrompt] checking if I can handle as array"); 916554f68d3SGreg Clayton if (!is_array && !is_pointer) 917554f68d3SGreg Clayton return false; 91863e5fb76SJonas Devlieghere LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array"); 919e8376261SVince Harron StreamString special_directions_stream; 920554f68d3SGreg Clayton llvm::StringRef special_directions; 921b9c1b51eSKate Stone if (close_bracket_index != llvm::StringRef::npos && 922b9c1b51eSKate Stone subpath.size() > close_bracket_index) { 923554f68d3SGreg Clayton ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); 924b9c1b51eSKate Stone special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", 925554f68d3SGreg Clayton additional_data.GetCString()); 926554f68d3SGreg Clayton 927b9c1b51eSKate Stone if (entry.fmt != eFormatDefault) { 928b9c1b51eSKate Stone const char format_char = 929b9c1b51eSKate Stone FormatManager::GetFormatAsFormatChar(entry.fmt); 930554f68d3SGreg Clayton if (format_char != '\0') 931554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", format_char); 932b9c1b51eSKate Stone else { 933b9c1b51eSKate Stone const char *format_cstr = 934b9c1b51eSKate Stone FormatManager::GetFormatAsCString(entry.fmt); 935554f68d3SGreg Clayton special_directions_stream.Printf("%%%s", format_cstr); 936554f68d3SGreg Clayton } 937b9c1b51eSKate Stone } else if (entry.number != 0) { 938b9c1b51eSKate Stone const char style_char = ConvertValueObjectStyleToChar( 939b9c1b51eSKate Stone (ValueObject::ValueObjectRepresentationStyle)entry.number); 940554f68d3SGreg Clayton if (style_char) 941554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", style_char); 942554f68d3SGreg Clayton } 943554f68d3SGreg Clayton special_directions_stream.PutChar('}'); 944b9c1b51eSKate Stone special_directions = 945b9c1b51eSKate Stone llvm::StringRef(special_directions_stream.GetString()); 946554f68d3SGreg Clayton } 947554f68d3SGreg Clayton 948554f68d3SGreg Clayton // let us display items index_lower thru index_higher of this array 949554f68d3SGreg Clayton s.PutChar('['); 950554f68d3SGreg Clayton 951554f68d3SGreg Clayton if (index_higher < 0) 952554f68d3SGreg Clayton index_higher = valobj->GetNumChildren() - 1; 953554f68d3SGreg Clayton 954b9c1b51eSKate Stone uint32_t max_num_children = 955b9c1b51eSKate Stone target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 956554f68d3SGreg Clayton 957554f68d3SGreg Clayton bool success = true; 958b9c1b51eSKate Stone for (int64_t index = index_lower; index <= index_higher; ++index) { 959b9c1b51eSKate Stone ValueObject *item = 960b9c1b51eSKate Stone ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) 961b9c1b51eSKate Stone .get(); 962554f68d3SGreg Clayton 963b9c1b51eSKate Stone if (!item) { 96463e5fb76SJonas Devlieghere LLDB_LOGF(log, 96563e5fb76SJonas Devlieghere "[Debugger::FormatPrompt] ERROR in getting child item at " 966b9c1b51eSKate Stone "index %" PRId64, 967b9c1b51eSKate Stone index); 968b9c1b51eSKate Stone } else { 96963e5fb76SJonas Devlieghere LLDB_LOGF( 97063e5fb76SJonas Devlieghere log, 971b9c1b51eSKate Stone "[Debugger::FormatPrompt] special_directions for child item: %s", 972b9c1b51eSKate Stone special_directions.data() ? special_directions.data() : ""); 973554f68d3SGreg Clayton } 974554f68d3SGreg Clayton 975b9c1b51eSKate Stone if (special_directions.empty()) { 976b9c1b51eSKate Stone success &= item->DumpPrintableRepresentation(s, val_obj_display, 977b9c1b51eSKate Stone custom_format); 978b9c1b51eSKate Stone } else { 979b9c1b51eSKate Stone success &= FormatEntity::FormatStringRef( 980b9c1b51eSKate Stone special_directions, s, sc, exe_ctx, nullptr, item, false, false); 981554f68d3SGreg Clayton } 982554f68d3SGreg Clayton 983b9c1b51eSKate Stone if (--max_num_children == 0) { 984554f68d3SGreg Clayton s.PutCString(", ..."); 985554f68d3SGreg Clayton break; 986554f68d3SGreg Clayton } 987554f68d3SGreg Clayton 988554f68d3SGreg Clayton if (index < index_higher) 989554f68d3SGreg Clayton s.PutChar(','); 990554f68d3SGreg Clayton } 991554f68d3SGreg Clayton s.PutChar(']'); 992554f68d3SGreg Clayton return success; 993554f68d3SGreg Clayton } 994554f68d3SGreg Clayton } 995554f68d3SGreg Clayton 996b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, 997b9c1b51eSKate Stone Format format) { 998b9c1b51eSKate Stone if (frame) { 999554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 1000554f68d3SGreg Clayton 1001b9c1b51eSKate Stone if (reg_ctx) { 1002554f68d3SGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 1003b9c1b51eSKate Stone if (reg_info) { 1004554f68d3SGreg Clayton RegisterValue reg_value; 1005b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 1006e03334cfSPavel Labath DumpRegisterValue(reg_value, &s, reg_info, false, false, format); 1007554f68d3SGreg Clayton return true; 1008554f68d3SGreg Clayton } 1009554f68d3SGreg Clayton } 1010554f68d3SGreg Clayton } 1011554f68d3SGreg Clayton } 1012554f68d3SGreg Clayton return false; 1013554f68d3SGreg Clayton } 1014554f68d3SGreg Clayton 1015b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse( 1016b9c1b51eSKate Stone const FormatEntity::Entry &entry, 1017554f68d3SGreg Clayton const StructuredData::ObjectSP &thread_info_dictionary, 1018b9c1b51eSKate Stone const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { 1019554f68d3SGreg Clayton llvm::StringRef path(entry.string); 1020554f68d3SGreg Clayton 1021b9c1b51eSKate Stone StructuredData::ObjectSP value = 1022b9c1b51eSKate Stone thread_info_dictionary->GetObjectForDotSeparatedPath(path); 1023554f68d3SGreg Clayton 1024b9c1b51eSKate Stone if (value) { 10255bfee5f1SAbhishek Aggarwal if (value->GetType() == eStructuredDataTypeInteger) { 1026554f68d3SGreg Clayton const char *token_format = "0x%4.4" PRIx64; 1027554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1028554f68d3SGreg Clayton token_format = entry.printf_format.c_str(); 1029554f68d3SGreg Clayton s.Printf(token_format, value->GetAsInteger()->GetValue()); 1030554f68d3SGreg Clayton return true; 10315bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeFloat) { 1032554f68d3SGreg Clayton s.Printf("%f", value->GetAsFloat()->GetValue()); 1033554f68d3SGreg Clayton return true; 10345bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeString) { 10352833321fSZachary Turner s.Format("{0}", value->GetAsString()->GetValue()); 1036554f68d3SGreg Clayton return true; 10375bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeArray) { 1038b9c1b51eSKate Stone if (value->GetAsArray()->GetSize() > 0) { 1039554f68d3SGreg Clayton s.Printf("%zu", value->GetAsArray()->GetSize()); 1040554f68d3SGreg Clayton return true; 1041554f68d3SGreg Clayton } 10425bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeDictionary) { 1043b9c1b51eSKate Stone s.Printf("%zu", 1044b9c1b51eSKate Stone value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1045554f68d3SGreg Clayton return true; 1046554f68d3SGreg Clayton } 1047554f68d3SGreg Clayton } 1048554f68d3SGreg Clayton 1049554f68d3SGreg Clayton return false; 1050554f68d3SGreg Clayton } 1051554f68d3SGreg Clayton 1052b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) { 1053554f68d3SGreg Clayton return (::strncmp(var_name_begin, var, strlen(var)) == 0); 1054554f68d3SGreg Clayton } 1055554f68d3SGreg Clayton 1056b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, 1057554f68d3SGreg Clayton const SymbolContext *sc, 1058554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1059b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1060554f68d3SGreg Clayton bool function_changed, 1061b9c1b51eSKate Stone bool initial_function) { 1062b9c1b51eSKate Stone if (!format_str.empty()) { 1063554f68d3SGreg Clayton FormatEntity::Entry root; 106497206d57SZachary Turner Status error = FormatEntity::Parse(format_str, root); 1065b9c1b51eSKate Stone if (error.Success()) { 1066b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1067b9c1b51eSKate Stone function_changed, initial_function); 1068554f68d3SGreg Clayton } 1069554f68d3SGreg Clayton } 1070554f68d3SGreg Clayton return false; 1071554f68d3SGreg Clayton } 1072a74f37a5SEugene Zelenko 1073b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s, 1074554f68d3SGreg Clayton const SymbolContext *sc, 1075554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1076b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1077b9c1b51eSKate Stone bool function_changed, bool initial_function) { 1078b9c1b51eSKate Stone if (format && format[0]) { 1079554f68d3SGreg Clayton FormatEntity::Entry root; 1080554f68d3SGreg Clayton llvm::StringRef format_str(format); 108197206d57SZachary Turner Status error = FormatEntity::Parse(format_str, root); 1082b9c1b51eSKate Stone if (error.Success()) { 1083b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1084b9c1b51eSKate Stone function_changed, initial_function); 1085554f68d3SGreg Clayton } 1086554f68d3SGreg Clayton } 1087554f68d3SGreg Clayton return false; 1088554f68d3SGreg Clayton } 1089554f68d3SGreg Clayton 1090b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s, 1091554f68d3SGreg Clayton const SymbolContext *sc, 1092b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address *addr, 1093b9c1b51eSKate Stone ValueObject *valobj, bool function_changed, 1094b9c1b51eSKate Stone bool initial_function) { 1095b9c1b51eSKate Stone switch (entry.type) { 1096554f68d3SGreg Clayton case Entry::Type::Invalid: 1097b9c1b51eSKate Stone case Entry::Type::ParentNumber: // Only used for 1098b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1099b9c1b51eSKate Stone case Entry::Type::ParentString: // Only used for 1100b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1101a33964b5SJonas Devlieghere return false; 1102a33964b5SJonas Devlieghere case Entry::Type::EscapeCode: 1103a33964b5SJonas Devlieghere if (exe_ctx) { 1104a33964b5SJonas Devlieghere if (Target *target = exe_ctx->GetTargetPtr()) { 1105a33964b5SJonas Devlieghere Debugger &debugger = target->GetDebugger(); 1106a33964b5SJonas Devlieghere if (debugger.GetUseColor()) { 1107a33964b5SJonas Devlieghere s.PutCString(entry.string); 1108f9626f27SJonas Devlieghere } 1109f9626f27SJonas Devlieghere } 1110f9626f27SJonas Devlieghere } 1111f9626f27SJonas Devlieghere // Always return true, so colors being disabled is transparent. 1112a33964b5SJonas Devlieghere return true; 1113554f68d3SGreg Clayton 1114554f68d3SGreg Clayton case Entry::Type::Root: 1115b9c1b51eSKate Stone for (const auto &child : entry.children) { 1116b9c1b51eSKate Stone if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, 1117b9c1b51eSKate Stone initial_function)) { 1118554f68d3SGreg Clayton return false; // If any item of root fails, then the formatting fails 1119554f68d3SGreg Clayton } 1120554f68d3SGreg Clayton } 1121554f68d3SGreg Clayton return true; // Only return true if all items succeeded 1122554f68d3SGreg Clayton 1123554f68d3SGreg Clayton case Entry::Type::String: 1124771ef6d4SMalcolm Parsons s.PutCString(entry.string); 1125554f68d3SGreg Clayton return true; 1126554f68d3SGreg Clayton 1127b9c1b51eSKate Stone case Entry::Type::Scope: { 1128554f68d3SGreg Clayton StreamString scope_stream; 1129554f68d3SGreg Clayton bool success = false; 1130b9c1b51eSKate Stone for (const auto &child : entry.children) { 1131b9c1b51eSKate Stone success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, 1132b9c1b51eSKate Stone function_changed, initial_function); 1133554f68d3SGreg Clayton if (!success) 1134554f68d3SGreg Clayton break; 1135554f68d3SGreg Clayton } 113605097246SAdrian Prantl // Only if all items in a scope succeed, then do we print the output into 113705097246SAdrian Prantl // the main stream 1138554f68d3SGreg Clayton if (success) 1139554f68d3SGreg Clayton s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1140554f68d3SGreg Clayton } 1141554f68d3SGreg Clayton return true; // Scopes always successfully print themselves 1142554f68d3SGreg Clayton 1143554f68d3SGreg Clayton case Entry::Type::Variable: 1144554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 1145554f68d3SGreg Clayton case Entry::Type::ScriptVariable: 1146554f68d3SGreg Clayton case Entry::Type::ScriptVariableSynthetic: 1147a74f37a5SEugene Zelenko return DumpValue(s, sc, exe_ctx, entry, valobj); 1148554f68d3SGreg Clayton 1149554f68d3SGreg Clayton case Entry::Type::AddressFile: 1150554f68d3SGreg Clayton case Entry::Type::AddressLoad: 1151554f68d3SGreg Clayton case Entry::Type::AddressLoadOrFile: 11521462f5a4SRaphael Isemann return ( 11531462f5a4SRaphael Isemann addr != nullptr && addr->IsValid() && 11541462f5a4SRaphael Isemann DumpAddressAndContent(s, sc, exe_ctx, *addr, 1155b9c1b51eSKate Stone entry.type == Entry::Type::AddressLoadOrFile)); 1156554f68d3SGreg Clayton 1157554f68d3SGreg Clayton case Entry::Type::ProcessID: 1158b9c1b51eSKate Stone if (exe_ctx) { 1159554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1160b9c1b51eSKate Stone if (process) { 1161554f68d3SGreg Clayton const char *format = "%" PRIu64; 1162554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1163554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1164554f68d3SGreg Clayton s.Printf(format, process->GetID()); 1165554f68d3SGreg Clayton return true; 1166554f68d3SGreg Clayton } 1167554f68d3SGreg Clayton } 1168554f68d3SGreg Clayton return false; 1169554f68d3SGreg Clayton 1170554f68d3SGreg Clayton case Entry::Type::ProcessFile: 1171b9c1b51eSKate Stone if (exe_ctx) { 1172554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1173b9c1b51eSKate Stone if (process) { 1174554f68d3SGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1175b9c1b51eSKate Stone if (exe_module) { 1176554f68d3SGreg Clayton if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1177554f68d3SGreg Clayton return true; 1178554f68d3SGreg Clayton } 1179554f68d3SGreg Clayton } 1180554f68d3SGreg Clayton } 1181554f68d3SGreg Clayton return false; 1182554f68d3SGreg Clayton 1183554f68d3SGreg Clayton case Entry::Type::ScriptProcess: 1184b9c1b51eSKate Stone if (exe_ctx) { 1185554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1186554f68d3SGreg Clayton if (process) 1187b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, process, 1188b9c1b51eSKate Stone entry.string.c_str()); 1189554f68d3SGreg Clayton } 1190554f68d3SGreg Clayton return false; 1191554f68d3SGreg Clayton 1192554f68d3SGreg Clayton case Entry::Type::ThreadID: 1193b9c1b51eSKate Stone if (exe_ctx) { 1194554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1195b9c1b51eSKate Stone if (thread) { 1196554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1197b9c1b51eSKate Stone if (!entry.printf_format.empty()) { 1198554f68d3SGreg Clayton // Watch for the special "tid" format... 1199b9c1b51eSKate Stone if (entry.printf_format == "tid") { 1200b9c1b51eSKate Stone // TODO(zturner): Rather than hardcoding this to be platform 120105097246SAdrian Prantl // specific, it should be controlled by a setting and the default 120205097246SAdrian Prantl // value of the setting can be different depending on the platform. 1203554f68d3SGreg Clayton Target &target = thread->GetProcess()->GetTarget(); 1204554f68d3SGreg Clayton ArchSpec arch(target.GetArchitecture()); 1205b9c1b51eSKate Stone llvm::Triple::OSType ostype = arch.IsValid() 1206b9c1b51eSKate Stone ? arch.GetTriple().getOS() 1207b9c1b51eSKate Stone : llvm::Triple::UnknownOS; 1208b9c1b51eSKate Stone if ((ostype == llvm::Triple::FreeBSD) || 1209750228a6SKamil Rytarowski (ostype == llvm::Triple::Linux) || 1210750228a6SKamil Rytarowski (ostype == llvm::Triple::NetBSD)) { 1211554f68d3SGreg Clayton format = "%" PRIu64; 1212554f68d3SGreg Clayton } 1213b9c1b51eSKate Stone } else { 1214554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1215554f68d3SGreg Clayton } 1216554f68d3SGreg Clayton } 1217554f68d3SGreg Clayton s.Printf(format, thread->GetID()); 1218554f68d3SGreg Clayton return true; 1219554f68d3SGreg Clayton } 1220554f68d3SGreg Clayton } 1221554f68d3SGreg Clayton return false; 1222554f68d3SGreg Clayton 1223554f68d3SGreg Clayton case Entry::Type::ThreadProtocolID: 1224b9c1b51eSKate Stone if (exe_ctx) { 1225554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1226b9c1b51eSKate Stone if (thread) { 1227554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1228554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1229554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1230554f68d3SGreg Clayton s.Printf(format, thread->GetProtocolID()); 1231554f68d3SGreg Clayton return true; 1232554f68d3SGreg Clayton } 1233554f68d3SGreg Clayton } 1234554f68d3SGreg Clayton return false; 1235554f68d3SGreg Clayton 1236554f68d3SGreg Clayton case Entry::Type::ThreadIndexID: 1237b9c1b51eSKate Stone if (exe_ctx) { 1238554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1239b9c1b51eSKate Stone if (thread) { 1240554f68d3SGreg Clayton const char *format = "%" PRIu32; 1241554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1242554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1243554f68d3SGreg Clayton s.Printf(format, thread->GetIndexID()); 1244554f68d3SGreg Clayton return true; 1245554f68d3SGreg Clayton } 1246554f68d3SGreg Clayton } 1247554f68d3SGreg Clayton return false; 1248554f68d3SGreg Clayton 1249554f68d3SGreg Clayton case Entry::Type::ThreadName: 1250b9c1b51eSKate Stone if (exe_ctx) { 1251554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1252b9c1b51eSKate Stone if (thread) { 1253554f68d3SGreg Clayton const char *cstr = thread->GetName(); 1254b9c1b51eSKate Stone if (cstr && cstr[0]) { 1255554f68d3SGreg Clayton s.PutCString(cstr); 1256554f68d3SGreg Clayton return true; 1257554f68d3SGreg Clayton } 1258554f68d3SGreg Clayton } 1259554f68d3SGreg Clayton } 1260554f68d3SGreg Clayton return false; 1261554f68d3SGreg Clayton 1262554f68d3SGreg Clayton case Entry::Type::ThreadQueue: 1263b9c1b51eSKate Stone if (exe_ctx) { 1264554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1265b9c1b51eSKate Stone if (thread) { 1266554f68d3SGreg Clayton const char *cstr = thread->GetQueueName(); 1267b9c1b51eSKate Stone if (cstr && cstr[0]) { 1268554f68d3SGreg Clayton s.PutCString(cstr); 1269554f68d3SGreg Clayton return true; 1270554f68d3SGreg Clayton } 1271554f68d3SGreg Clayton } 1272554f68d3SGreg Clayton } 1273554f68d3SGreg Clayton return false; 1274554f68d3SGreg Clayton 1275554f68d3SGreg Clayton case Entry::Type::ThreadStopReason: 1276b9c1b51eSKate Stone if (exe_ctx) { 12777ebe9cc4SMed Ismail Bennani if (Thread *thread = exe_ctx->GetThreadPtr()) { 12787ebe9cc4SMed Ismail Bennani std::string stop_description = thread->GetStopDescription(); 12797ebe9cc4SMed Ismail Bennani if (!stop_description.empty()) { 12807ebe9cc4SMed Ismail Bennani s.PutCString(stop_description); 1281554f68d3SGreg Clayton return true; 1282554f68d3SGreg Clayton } 1283554f68d3SGreg Clayton } 1284554f68d3SGreg Clayton } 12857ebe9cc4SMed Ismail Bennani return false; 12867ebe9cc4SMed Ismail Bennani 12877ebe9cc4SMed Ismail Bennani case Entry::Type::ThreadStopReasonRaw: 12887ebe9cc4SMed Ismail Bennani if (exe_ctx) { 12897ebe9cc4SMed Ismail Bennani if (Thread *thread = exe_ctx->GetThreadPtr()) { 12907ebe9cc4SMed Ismail Bennani std::string stop_description = thread->GetStopDescriptionRaw(); 12917ebe9cc4SMed Ismail Bennani if (!stop_description.empty()) { 12927ebe9cc4SMed Ismail Bennani s.PutCString(stop_description); 12937ebe9cc4SMed Ismail Bennani return true; 12947ebe9cc4SMed Ismail Bennani } 12957ebe9cc4SMed Ismail Bennani } 1296554f68d3SGreg Clayton } 1297554f68d3SGreg Clayton return false; 1298554f68d3SGreg Clayton 1299554f68d3SGreg Clayton case Entry::Type::ThreadReturnValue: 1300b9c1b51eSKate Stone if (exe_ctx) { 1301554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1302b9c1b51eSKate Stone if (thread) { 1303554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1304b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1305b9c1b51eSKate Stone ValueObjectSP return_valobj_sp = 1306b9c1b51eSKate Stone StopInfo::GetReturnValueObject(stop_info_sp); 1307b9c1b51eSKate Stone if (return_valobj_sp) { 1308554f68d3SGreg Clayton return_valobj_sp->Dump(s); 1309554f68d3SGreg Clayton return true; 1310554f68d3SGreg Clayton } 1311554f68d3SGreg Clayton } 1312554f68d3SGreg Clayton } 1313554f68d3SGreg Clayton } 1314554f68d3SGreg Clayton return false; 1315554f68d3SGreg Clayton 1316554f68d3SGreg Clayton case Entry::Type::ThreadCompletedExpression: 1317b9c1b51eSKate Stone if (exe_ctx) { 1318554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1319b9c1b51eSKate Stone if (thread) { 1320554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1321b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1322b9c1b51eSKate Stone ExpressionVariableSP expression_var_sp = 1323b9c1b51eSKate Stone StopInfo::GetExpressionVariable(stop_info_sp); 1324b9c1b51eSKate Stone if (expression_var_sp && expression_var_sp->GetValueObject()) { 1325554f68d3SGreg Clayton expression_var_sp->GetValueObject()->Dump(s); 1326554f68d3SGreg Clayton return true; 1327554f68d3SGreg Clayton } 1328554f68d3SGreg Clayton } 1329554f68d3SGreg Clayton } 1330554f68d3SGreg Clayton } 1331554f68d3SGreg Clayton return false; 1332554f68d3SGreg Clayton 1333554f68d3SGreg Clayton case Entry::Type::ScriptThread: 1334b9c1b51eSKate Stone if (exe_ctx) { 1335554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1336554f68d3SGreg Clayton if (thread) 1337b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, thread, 1338b9c1b51eSKate Stone entry.string.c_str()); 1339554f68d3SGreg Clayton } 1340554f68d3SGreg Clayton return false; 1341554f68d3SGreg Clayton 1342554f68d3SGreg Clayton case Entry::Type::ThreadInfo: 1343b9c1b51eSKate Stone if (exe_ctx) { 1344554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1345b9c1b51eSKate Stone if (thread) { 1346554f68d3SGreg Clayton StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1347b9c1b51eSKate Stone if (object_sp && 13485bfee5f1SAbhishek Aggarwal object_sp->GetType() == eStructuredDataTypeDictionary) { 1349554f68d3SGreg Clayton if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) 1350554f68d3SGreg Clayton return true; 1351554f68d3SGreg Clayton } 1352554f68d3SGreg Clayton } 1353554f68d3SGreg Clayton } 1354554f68d3SGreg Clayton return false; 1355554f68d3SGreg Clayton 1356554f68d3SGreg Clayton case Entry::Type::TargetArch: 1357b9c1b51eSKate Stone if (exe_ctx) { 1358554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1359b9c1b51eSKate Stone if (target) { 1360554f68d3SGreg Clayton const ArchSpec &arch = target->GetArchitecture(); 1361b9c1b51eSKate Stone if (arch.IsValid()) { 1362554f68d3SGreg Clayton s.PutCString(arch.GetArchitectureName()); 1363554f68d3SGreg Clayton return true; 1364554f68d3SGreg Clayton } 1365554f68d3SGreg Clayton } 1366554f68d3SGreg Clayton } 1367554f68d3SGreg Clayton return false; 1368554f68d3SGreg Clayton 1369554f68d3SGreg Clayton case Entry::Type::ScriptTarget: 1370b9c1b51eSKate Stone if (exe_ctx) { 1371554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1372554f68d3SGreg Clayton if (target) 1373b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, target, 1374b9c1b51eSKate Stone entry.string.c_str()); 1375554f68d3SGreg Clayton } 1376554f68d3SGreg Clayton return false; 1377554f68d3SGreg Clayton 1378554f68d3SGreg Clayton case Entry::Type::ModuleFile: 1379b9c1b51eSKate Stone if (sc) { 1380554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1381b9c1b51eSKate Stone if (module) { 1382554f68d3SGreg Clayton if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1383554f68d3SGreg Clayton return true; 1384554f68d3SGreg Clayton } 1385554f68d3SGreg Clayton } 1386554f68d3SGreg Clayton return false; 1387554f68d3SGreg Clayton 1388554f68d3SGreg Clayton case Entry::Type::File: 1389b9c1b51eSKate Stone if (sc) { 1390554f68d3SGreg Clayton CompileUnit *cu = sc->comp_unit; 1391b9c1b51eSKate Stone if (cu) { 139238870af8SPavel Labath if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number)) 1393554f68d3SGreg Clayton return true; 1394554f68d3SGreg Clayton } 1395554f68d3SGreg Clayton } 1396554f68d3SGreg Clayton return false; 1397554f68d3SGreg Clayton 1398dc975670SDawn Perchik case Entry::Type::Lang: 1399b9c1b51eSKate Stone if (sc) { 1400dc975670SDawn Perchik CompileUnit *cu = sc->comp_unit; 1401b9c1b51eSKate Stone if (cu) { 1402b9c1b51eSKate Stone const char *lang_name = 1403b9c1b51eSKate Stone Language::GetNameForLanguageType(cu->GetLanguage()); 1404b9c1b51eSKate Stone if (lang_name) { 1405dc975670SDawn Perchik s.PutCString(lang_name); 1406dc975670SDawn Perchik return true; 1407dc975670SDawn Perchik } 1408dc975670SDawn Perchik } 1409dc975670SDawn Perchik } 1410dc975670SDawn Perchik return false; 1411dc975670SDawn Perchik 1412554f68d3SGreg Clayton case Entry::Type::FrameIndex: 1413b9c1b51eSKate Stone if (exe_ctx) { 1414554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1415b9c1b51eSKate Stone if (frame) { 1416554f68d3SGreg Clayton const char *format = "%" PRIu32; 1417554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1418554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1419554f68d3SGreg Clayton s.Printf(format, frame->GetFrameIndex()); 1420554f68d3SGreg Clayton return true; 1421554f68d3SGreg Clayton } 1422554f68d3SGreg Clayton } 1423554f68d3SGreg Clayton return false; 1424554f68d3SGreg Clayton 1425554f68d3SGreg Clayton case Entry::Type::FrameRegisterPC: 1426b9c1b51eSKate Stone if (exe_ctx) { 1427554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1428b9c1b51eSKate Stone if (frame) { 1429554f68d3SGreg Clayton const Address &pc_addr = frame->GetFrameCodeAddress(); 1430b9c1b51eSKate Stone if (pc_addr.IsValid()) { 14311462f5a4SRaphael Isemann if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false)) 1432554f68d3SGreg Clayton return true; 1433554f68d3SGreg Clayton } 1434554f68d3SGreg Clayton } 1435554f68d3SGreg Clayton } 1436554f68d3SGreg Clayton return false; 1437554f68d3SGreg Clayton 1438554f68d3SGreg Clayton case Entry::Type::FrameRegisterSP: 1439b9c1b51eSKate Stone if (exe_ctx) { 1440554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1441b9c1b51eSKate Stone if (frame) { 1442b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 1443b9c1b51eSKate Stone (lldb::Format)entry.number)) 1444554f68d3SGreg Clayton return true; 1445554f68d3SGreg Clayton } 1446554f68d3SGreg Clayton } 1447554f68d3SGreg Clayton return false; 1448554f68d3SGreg Clayton 1449554f68d3SGreg Clayton case Entry::Type::FrameRegisterFP: 1450b9c1b51eSKate Stone if (exe_ctx) { 1451554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1452b9c1b51eSKate Stone if (frame) { 1453b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, 1454b9c1b51eSKate Stone (lldb::Format)entry.number)) 1455554f68d3SGreg Clayton return true; 1456554f68d3SGreg Clayton } 1457554f68d3SGreg Clayton } 1458554f68d3SGreg Clayton return false; 1459554f68d3SGreg Clayton 1460554f68d3SGreg Clayton case Entry::Type::FrameRegisterFlags: 1461b9c1b51eSKate Stone if (exe_ctx) { 1462554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1463b9c1b51eSKate Stone if (frame) { 1464b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, 1465b9c1b51eSKate Stone LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1466554f68d3SGreg Clayton return true; 1467554f68d3SGreg Clayton } 1468554f68d3SGreg Clayton } 1469554f68d3SGreg Clayton return false; 1470554f68d3SGreg Clayton 14716a9767c7SJim Ingham case Entry::Type::FrameNoDebug: 14726a9767c7SJim Ingham if (exe_ctx) { 14736a9767c7SJim Ingham StackFrame *frame = exe_ctx->GetFramePtr(); 14746a9767c7SJim Ingham if (frame) { 14756a9767c7SJim Ingham return !frame->HasDebugInformation(); 14766a9767c7SJim Ingham } 14776a9767c7SJim Ingham } 14786a9767c7SJim Ingham return true; 14796a9767c7SJim Ingham 1480554f68d3SGreg Clayton case Entry::Type::FrameRegisterByName: 1481b9c1b51eSKate Stone if (exe_ctx) { 1482554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1483b9c1b51eSKate Stone if (frame) { 1484b9c1b51eSKate Stone if (DumpRegister(s, frame, entry.string.c_str(), 1485b9c1b51eSKate Stone (lldb::Format)entry.number)) 1486554f68d3SGreg Clayton return true; 1487554f68d3SGreg Clayton } 1488554f68d3SGreg Clayton } 1489554f68d3SGreg Clayton return false; 1490554f68d3SGreg Clayton 14914b36f791SVedant Kumar case Entry::Type::FrameIsArtificial: { 14924b36f791SVedant Kumar if (exe_ctx) 14934b36f791SVedant Kumar if (StackFrame *frame = exe_ctx->GetFramePtr()) 14944b36f791SVedant Kumar return frame->IsArtificial(); 14954b36f791SVedant Kumar return false; 14964b36f791SVedant Kumar } 14974b36f791SVedant Kumar 1498554f68d3SGreg Clayton case Entry::Type::ScriptFrame: 1499b9c1b51eSKate Stone if (exe_ctx) { 1500554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1501554f68d3SGreg Clayton if (frame) 1502b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, frame, 1503b9c1b51eSKate Stone entry.string.c_str()); 1504554f68d3SGreg Clayton } 1505554f68d3SGreg Clayton return false; 1506554f68d3SGreg Clayton 1507554f68d3SGreg Clayton case Entry::Type::FunctionID: 1508b9c1b51eSKate Stone if (sc) { 1509b9c1b51eSKate Stone if (sc->function) { 1510554f68d3SGreg Clayton s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1511554f68d3SGreg Clayton return true; 1512b9c1b51eSKate Stone } else if (sc->symbol) { 1513554f68d3SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 1514554f68d3SGreg Clayton return true; 1515554f68d3SGreg Clayton } 1516554f68d3SGreg Clayton } 1517554f68d3SGreg Clayton return false; 1518554f68d3SGreg Clayton 1519554f68d3SGreg Clayton case Entry::Type::FunctionDidChange: 1520554f68d3SGreg Clayton return function_changed; 1521554f68d3SGreg Clayton 1522554f68d3SGreg Clayton case Entry::Type::FunctionInitialFunction: 1523554f68d3SGreg Clayton return initial_function; 1524554f68d3SGreg Clayton 1525b9c1b51eSKate Stone case Entry::Type::FunctionName: { 1526d4129b47SEnrico Granata Language *language_plugin = nullptr; 1527d4129b47SEnrico Granata bool language_plugin_handled = false; 1528d4129b47SEnrico Granata StreamString ss; 1529d4129b47SEnrico Granata if (sc->function) 1530d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1531d4129b47SEnrico Granata else if (sc->symbol) 1532d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1533b9c1b51eSKate Stone if (language_plugin) { 1534b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1535b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); 1536d4129b47SEnrico Granata } 1537b9c1b51eSKate Stone if (language_plugin_handled) { 1538c156427dSZachary Turner s << ss.GetString(); 1539d4129b47SEnrico Granata return true; 1540b9c1b51eSKate Stone } else { 1541a74f37a5SEugene Zelenko const char *name = nullptr; 1542554f68d3SGreg Clayton if (sc->function) 1543a74f37a5SEugene Zelenko name = sc->function->GetName().AsCString(nullptr); 1544554f68d3SGreg Clayton else if (sc->symbol) 1545a74f37a5SEugene Zelenko name = sc->symbol->GetName().AsCString(nullptr); 1546b9c1b51eSKate Stone if (name) { 1547554f68d3SGreg Clayton s.PutCString(name); 1548554f68d3SGreg Clayton 1549b9c1b51eSKate Stone if (sc->block) { 1550554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1551b9c1b51eSKate Stone if (inline_block) { 1552b9c1b51eSKate Stone const InlineFunctionInfo *inline_info = 1553b9c1b51eSKate Stone sc->block->GetInlinedFunctionInfo(); 1554b9c1b51eSKate Stone if (inline_info) { 1555554f68d3SGreg Clayton s.PutCString(" [inlined] "); 155622b04487SAlex Langford inline_info->GetName().Dump(&s); 1557554f68d3SGreg Clayton } 1558554f68d3SGreg Clayton } 1559554f68d3SGreg Clayton } 1560554f68d3SGreg Clayton return true; 1561554f68d3SGreg Clayton } 1562554f68d3SGreg Clayton } 1563d4129b47SEnrico Granata } 1564554f68d3SGreg Clayton return false; 1565554f68d3SGreg Clayton 1566b9c1b51eSKate Stone case Entry::Type::FunctionNameNoArgs: { 1567d4129b47SEnrico Granata Language *language_plugin = nullptr; 1568d4129b47SEnrico Granata bool language_plugin_handled = false; 1569d4129b47SEnrico Granata StreamString ss; 1570d4129b47SEnrico Granata if (sc->function) 1571d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1572d4129b47SEnrico Granata else if (sc->symbol) 1573d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1574b9c1b51eSKate Stone if (language_plugin) { 1575b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1576b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, 1577d4129b47SEnrico Granata ss); 1578d4129b47SEnrico Granata } 1579b9c1b51eSKate Stone if (language_plugin_handled) { 1580c156427dSZachary Turner s << ss.GetString(); 1581d4129b47SEnrico Granata return true; 1582b9c1b51eSKate Stone } else { 1583554f68d3SGreg Clayton ConstString name; 1584554f68d3SGreg Clayton if (sc->function) 1585ddaf6a72SGreg Clayton name = sc->function->GetNameNoArguments(); 1586554f68d3SGreg Clayton else if (sc->symbol) 1587ddaf6a72SGreg Clayton name = sc->symbol->GetNameNoArguments(); 1588b9c1b51eSKate Stone if (name) { 1589554f68d3SGreg Clayton s.PutCString(name.GetCString()); 1590554f68d3SGreg Clayton return true; 1591554f68d3SGreg Clayton } 1592554f68d3SGreg Clayton } 1593d4129b47SEnrico Granata } 1594554f68d3SGreg Clayton return false; 1595554f68d3SGreg Clayton 1596b9c1b51eSKate Stone case Entry::Type::FunctionNameWithArgs: { 1597d4129b47SEnrico Granata Language *language_plugin = nullptr; 1598d4129b47SEnrico Granata bool language_plugin_handled = false; 1599d4129b47SEnrico Granata StreamString ss; 1600d4129b47SEnrico Granata if (sc->function) 1601d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1602d4129b47SEnrico Granata else if (sc->symbol) 1603d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1604b9c1b51eSKate Stone if (language_plugin) { 1605b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1606b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); 1607d4129b47SEnrico Granata } 1608b9c1b51eSKate Stone if (language_plugin_handled) { 1609c156427dSZachary Turner s << ss.GetString(); 1610d4129b47SEnrico Granata return true; 1611b9c1b51eSKate Stone } else { 1612554f68d3SGreg Clayton // Print the function name with arguments in it 1613b9c1b51eSKate Stone if (sc->function) { 1614b9c1b51eSKate Stone ExecutionContextScope *exe_scope = 1615b9c1b51eSKate Stone exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 1616a74f37a5SEugene Zelenko const char *cstr = sc->function->GetName().AsCString(nullptr); 1617b9c1b51eSKate Stone if (cstr) { 1618a74f37a5SEugene Zelenko const InlineFunctionInfo *inline_info = nullptr; 1619554f68d3SGreg Clayton VariableListSP variable_list_sp; 1620554f68d3SGreg Clayton bool get_function_vars = true; 1621b9c1b51eSKate Stone if (sc->block) { 1622554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1623554f68d3SGreg Clayton 1624b9c1b51eSKate Stone if (inline_block) { 1625554f68d3SGreg Clayton get_function_vars = false; 1626554f68d3SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 1627554f68d3SGreg Clayton if (inline_info) 1628554f68d3SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList(true); 1629554f68d3SGreg Clayton } 1630554f68d3SGreg Clayton } 1631554f68d3SGreg Clayton 1632b9c1b51eSKate Stone if (get_function_vars) { 1633b9c1b51eSKate Stone variable_list_sp = 1634b9c1b51eSKate Stone sc->function->GetBlock(true).GetBlockVariableList(true); 1635554f68d3SGreg Clayton } 1636554f68d3SGreg Clayton 1637b9c1b51eSKate Stone if (inline_info) { 1638554f68d3SGreg Clayton s.PutCString(cstr); 1639554f68d3SGreg Clayton s.PutCString(" [inlined] "); 164022b04487SAlex Langford cstr = inline_info->GetName().GetCString(); 1641554f68d3SGreg Clayton } 1642554f68d3SGreg Clayton 1643554f68d3SGreg Clayton VariableList args; 1644554f68d3SGreg Clayton if (variable_list_sp) 1645b9c1b51eSKate Stone variable_list_sp->AppendVariablesWithScope( 1646b9c1b51eSKate Stone eValueTypeVariableArgument, args); 1647b9c1b51eSKate Stone if (args.GetSize() > 0) { 1648554f68d3SGreg Clayton const char *open_paren = strchr(cstr, '('); 1649554f68d3SGreg Clayton const char *close_paren = nullptr; 1650554f68d3SGreg Clayton const char *generic = strchr(cstr, '<'); 1651554f68d3SGreg Clayton // if before the arguments list begins there is a template sign 1652554f68d3SGreg Clayton // then scan to the end of the generic args before you try to find 1653554f68d3SGreg Clayton // the arguments list 1654b9c1b51eSKate Stone if (generic && open_paren && generic < open_paren) { 1655554f68d3SGreg Clayton int generic_depth = 1; 1656554f68d3SGreg Clayton ++generic; 1657b9c1b51eSKate Stone for (; *generic && generic_depth > 0; generic++) { 1658554f68d3SGreg Clayton if (*generic == '<') 1659554f68d3SGreg Clayton generic_depth++; 1660554f68d3SGreg Clayton if (*generic == '>') 1661554f68d3SGreg Clayton generic_depth--; 1662554f68d3SGreg Clayton } 1663554f68d3SGreg Clayton if (*generic) 1664554f68d3SGreg Clayton open_paren = strchr(generic, '('); 1665554f68d3SGreg Clayton else 1666554f68d3SGreg Clayton open_paren = nullptr; 1667554f68d3SGreg Clayton } 1668b9c1b51eSKate Stone if (open_paren) { 1669b9c1b51eSKate Stone if (IsToken(open_paren, "(anonymous namespace)")) { 1670b9c1b51eSKate Stone open_paren = 1671b9c1b51eSKate Stone strchr(open_paren + strlen("(anonymous namespace)"), '('); 1672554f68d3SGreg Clayton if (open_paren) 1673554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1674b9c1b51eSKate Stone } else 1675554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1676554f68d3SGreg Clayton } 1677554f68d3SGreg Clayton 1678554f68d3SGreg Clayton if (open_paren) 1679554f68d3SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 1680b9c1b51eSKate Stone else { 1681554f68d3SGreg Clayton s.PutCString(cstr); 1682554f68d3SGreg Clayton s.PutChar('('); 1683554f68d3SGreg Clayton } 1684554f68d3SGreg Clayton const size_t num_args = args.GetSize(); 1685b9c1b51eSKate Stone for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { 1686554f68d3SGreg Clayton std::string buffer; 1687554f68d3SGreg Clayton 1688554f68d3SGreg Clayton VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); 1689b9c1b51eSKate Stone ValueObjectSP var_value_sp( 1690b9c1b51eSKate Stone ValueObjectVariable::Create(exe_scope, var_sp)); 1691ad91c7ceSEnrico Granata StreamString ss; 1692c156427dSZachary Turner llvm::StringRef var_representation; 1693554f68d3SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 1694b9c1b51eSKate Stone if (var_value_sp->GetCompilerType().IsValid()) { 1695ad91c7ceSEnrico Granata if (var_value_sp && exe_scope->CalculateTarget()) 1696b9c1b51eSKate Stone var_value_sp = 1697b9c1b51eSKate Stone var_value_sp->GetQualifiedRepresentationIfAvailable( 1698b9c1b51eSKate Stone exe_scope->CalculateTarget() 1699b9c1b51eSKate Stone ->TargetProperties::GetPreferDynamicValue(), 1700b9c1b51eSKate Stone exe_scope->CalculateTarget() 1701b9c1b51eSKate Stone ->TargetProperties::GetEnableSyntheticValue()); 170299558cc4SGreg Clayton if (var_value_sp->GetCompilerType().IsAggregateType() && 1703b9c1b51eSKate Stone DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { 1704b9c1b51eSKate Stone static StringSummaryFormat format( 1705b9c1b51eSKate Stone TypeSummaryImpl::Flags() 1706554f68d3SGreg Clayton .SetHideItemNames(false) 1707554f68d3SGreg Clayton .SetShowMembersOneLiner(true), 1708554f68d3SGreg Clayton ""); 1709b9c1b51eSKate Stone format.FormatObject(var_value_sp.get(), buffer, 1710b9c1b51eSKate Stone TypeSummaryOptions()); 1711c156427dSZachary Turner var_representation = buffer; 1712b9c1b51eSKate Stone } else 1713b9c1b51eSKate Stone var_value_sp->DumpPrintableRepresentation( 171440dfc392SJonas Devlieghere ss, 171540dfc392SJonas Devlieghere ValueObject::ValueObjectRepresentationStyle:: 1716b9c1b51eSKate Stone eValueObjectRepresentationStyleSummary, 1717ad91c7ceSEnrico Granata eFormatDefault, 171865d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eAllow, 1719ad91c7ceSEnrico Granata false); 1720ad91c7ceSEnrico Granata } 1721ad91c7ceSEnrico Granata 1722c156427dSZachary Turner if (!ss.GetString().empty()) 1723c156427dSZachary Turner var_representation = ss.GetString(); 1724554f68d3SGreg Clayton if (arg_idx > 0) 1725554f68d3SGreg Clayton s.PutCString(", "); 1726b9c1b51eSKate Stone if (var_value_sp->GetError().Success()) { 1727c156427dSZachary Turner if (!var_representation.empty()) 1728c156427dSZachary Turner s.Printf("%s=%s", var_name, var_representation.str().c_str()); 1729554f68d3SGreg Clayton else 1730b9c1b51eSKate Stone s.Printf("%s=%s at %s", var_name, 1731b9c1b51eSKate Stone var_value_sp->GetTypeName().GetCString(), 1732b9c1b51eSKate Stone var_value_sp->GetLocationAsCString()); 1733b9c1b51eSKate Stone } else 1734554f68d3SGreg Clayton s.Printf("%s=<unavailable>", var_name); 1735554f68d3SGreg Clayton } 1736554f68d3SGreg Clayton 1737554f68d3SGreg Clayton if (close_paren) 1738554f68d3SGreg Clayton s.PutCString(close_paren); 1739554f68d3SGreg Clayton else 1740554f68d3SGreg Clayton s.PutChar(')'); 1741554f68d3SGreg Clayton 1742b9c1b51eSKate Stone } else { 1743554f68d3SGreg Clayton s.PutCString(cstr); 1744554f68d3SGreg Clayton } 1745554f68d3SGreg Clayton return true; 1746554f68d3SGreg Clayton } 1747b9c1b51eSKate Stone } else if (sc->symbol) { 1748a74f37a5SEugene Zelenko const char *cstr = sc->symbol->GetName().AsCString(nullptr); 1749b9c1b51eSKate Stone if (cstr) { 1750554f68d3SGreg Clayton s.PutCString(cstr); 1751554f68d3SGreg Clayton return true; 1752554f68d3SGreg Clayton } 1753554f68d3SGreg Clayton } 1754554f68d3SGreg Clayton } 1755d4129b47SEnrico Granata } 1756554f68d3SGreg Clayton return false; 1757554f68d3SGreg Clayton 17587eaae939SMed Ismail Bennani case Entry::Type::FunctionMangledName: { 17597eaae939SMed Ismail Bennani const char *name = nullptr; 17607eaae939SMed Ismail Bennani if (sc->symbol) 176122b04487SAlex Langford name = 176222b04487SAlex Langford sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString(); 17637eaae939SMed Ismail Bennani else if (sc->function) 17647eaae939SMed Ismail Bennani name = sc->function->GetMangled() 176522b04487SAlex Langford .GetName(Mangled::ePreferMangled) 17667eaae939SMed Ismail Bennani .AsCString(); 17677eaae939SMed Ismail Bennani 17687eaae939SMed Ismail Bennani if (!name) 17697eaae939SMed Ismail Bennani return false; 17707eaae939SMed Ismail Bennani s.PutCString(name); 17717eaae939SMed Ismail Bennani 1772*7dc324aaSDave Lee if (sc->block && sc->block->GetContainingInlinedBlock()) { 17737eaae939SMed Ismail Bennani if (const InlineFunctionInfo *inline_info = 17747eaae939SMed Ismail Bennani sc->block->GetInlinedFunctionInfo()) { 17757eaae939SMed Ismail Bennani s.PutCString(" [inlined] "); 177622b04487SAlex Langford inline_info->GetName().Dump(&s); 17777eaae939SMed Ismail Bennani } 17787eaae939SMed Ismail Bennani } 17797eaae939SMed Ismail Bennani return true; 17807eaae939SMed Ismail Bennani } 17817eaae939SMed Ismail Bennani 1782554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffset: 1783b9c1b51eSKate Stone if (addr) { 1784b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, 1785b9c1b51eSKate Stone false)) 1786554f68d3SGreg Clayton return true; 1787554f68d3SGreg Clayton } 1788554f68d3SGreg Clayton return false; 1789554f68d3SGreg Clayton 1790554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffsetConcrete: 1791b9c1b51eSKate Stone if (addr) { 1792b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, 1793b9c1b51eSKate Stone true)) 1794554f68d3SGreg Clayton return true; 1795554f68d3SGreg Clayton } 1796554f68d3SGreg Clayton return false; 1797554f68d3SGreg Clayton 1798554f68d3SGreg Clayton case Entry::Type::FunctionLineOffset: 1799b9c1b51eSKate Stone return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1800b9c1b51eSKate Stone sc->line_entry.range.GetBaseAddress(), 1801b9c1b51eSKate Stone false, false, false)); 1802554f68d3SGreg Clayton 1803554f68d3SGreg Clayton case Entry::Type::FunctionPCOffset: 1804b9c1b51eSKate Stone if (exe_ctx) { 1805554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1806b9c1b51eSKate Stone if (frame) { 1807b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1808b9c1b51eSKate Stone frame->GetFrameCodeAddress(), false, 1809b9c1b51eSKate Stone false, false)) 1810554f68d3SGreg Clayton return true; 1811554f68d3SGreg Clayton } 1812554f68d3SGreg Clayton } 1813554f68d3SGreg Clayton return false; 1814554f68d3SGreg Clayton 1815c980fa92SJason Molenda case Entry::Type::FunctionChanged: 1816a74f37a5SEugene Zelenko return function_changed; 1817c980fa92SJason Molenda 1818b9c1b51eSKate Stone case Entry::Type::FunctionIsOptimized: { 18196ab659a9SJason Molenda bool is_optimized = false; 1820b9c1b51eSKate Stone if (sc->function && sc->function->GetIsOptimized()) { 18216ab659a9SJason Molenda is_optimized = true; 18226ab659a9SJason Molenda } 18236ab659a9SJason Molenda return is_optimized; 18246ab659a9SJason Molenda } 18256ab659a9SJason Molenda 1826c980fa92SJason Molenda case Entry::Type::FunctionInitial: 1827a74f37a5SEugene Zelenko return initial_function; 1828c980fa92SJason Molenda 1829554f68d3SGreg Clayton case Entry::Type::LineEntryFile: 1830b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1831554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1832b9c1b51eSKate Stone if (module) { 1833554f68d3SGreg Clayton if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1834554f68d3SGreg Clayton return true; 1835554f68d3SGreg Clayton } 1836554f68d3SGreg Clayton } 1837554f68d3SGreg Clayton return false; 1838554f68d3SGreg Clayton 1839554f68d3SGreg Clayton case Entry::Type::LineEntryLineNumber: 1840b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1841554f68d3SGreg Clayton const char *format = "%" PRIu32; 1842554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1843554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1844554f68d3SGreg Clayton s.Printf(format, sc->line_entry.line); 1845554f68d3SGreg Clayton return true; 1846554f68d3SGreg Clayton } 1847554f68d3SGreg Clayton return false; 1848554f68d3SGreg Clayton 18494954f6a5SAdrian Prantl case Entry::Type::LineEntryColumn: 18504954f6a5SAdrian Prantl if (sc && sc->line_entry.IsValid() && sc->line_entry.column) { 18514954f6a5SAdrian Prantl const char *format = "%" PRIu32; 18524954f6a5SAdrian Prantl if (!entry.printf_format.empty()) 18534954f6a5SAdrian Prantl format = entry.printf_format.c_str(); 18544954f6a5SAdrian Prantl s.Printf(format, sc->line_entry.column); 18554954f6a5SAdrian Prantl return true; 18564954f6a5SAdrian Prantl } 18574954f6a5SAdrian Prantl return false; 18584954f6a5SAdrian Prantl 1859554f68d3SGreg Clayton case Entry::Type::LineEntryStartAddress: 1860554f68d3SGreg Clayton case Entry::Type::LineEntryEndAddress: 1861b9c1b51eSKate Stone if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { 1862554f68d3SGreg Clayton Address addr = sc->line_entry.range.GetBaseAddress(); 1863554f68d3SGreg Clayton 1864554f68d3SGreg Clayton if (entry.type == Entry::Type::LineEntryEndAddress) 1865554f68d3SGreg Clayton addr.Slide(sc->line_entry.range.GetByteSize()); 18661462f5a4SRaphael Isemann if (DumpAddressAndContent(s, sc, exe_ctx, addr, false)) 1867554f68d3SGreg Clayton return true; 1868554f68d3SGreg Clayton } 1869554f68d3SGreg Clayton return false; 1870554f68d3SGreg Clayton 1871554f68d3SGreg Clayton case Entry::Type::CurrentPCArrow: 1872b9c1b51eSKate Stone if (addr && exe_ctx && exe_ctx->GetFramePtr()) { 1873b9c1b51eSKate Stone RegisterContextSP reg_ctx = 1874b9c1b51eSKate Stone exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1875b9c1b51eSKate Stone if (reg_ctx) { 1876554f68d3SGreg Clayton addr_t pc_loadaddr = reg_ctx->GetPC(); 1877b9c1b51eSKate Stone if (pc_loadaddr != LLDB_INVALID_ADDRESS) { 1878554f68d3SGreg Clayton Address pc; 1879554f68d3SGreg Clayton pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); 1880b9c1b51eSKate Stone if (pc == *addr) { 1881554f68d3SGreg Clayton s.Printf("-> "); 1882554f68d3SGreg Clayton return true; 1883554f68d3SGreg Clayton } 1884554f68d3SGreg Clayton } 1885554f68d3SGreg Clayton } 1886554f68d3SGreg Clayton s.Printf(" "); 1887554f68d3SGreg Clayton return true; 1888554f68d3SGreg Clayton } 1889554f68d3SGreg Clayton return false; 1890554f68d3SGreg Clayton } 1891554f68d3SGreg Clayton return false; 1892554f68d3SGreg Clayton } 1893554f68d3SGreg Clayton 1894b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames( 1895b9c1b51eSKate Stone Stream &s, const FormatEntity::Entry::Definition *parent) { 1896b9c1b51eSKate Stone if (parent->children) { 1897554f68d3SGreg Clayton const size_t n = parent->num_children; 1898b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1899554f68d3SGreg Clayton if (i > 0) 1900554f68d3SGreg Clayton s.PutCString(", "); 1901554f68d3SGreg Clayton s.Printf("\"%s\"", parent->children[i].name); 1902554f68d3SGreg Clayton } 1903554f68d3SGreg Clayton return true; 1904554f68d3SGreg Clayton } 1905554f68d3SGreg Clayton return false; 1906554f68d3SGreg Clayton } 1907554f68d3SGreg Clayton 190897206d57SZachary Turner static Status ParseEntry(const llvm::StringRef &format_str, 1909554f68d3SGreg Clayton const FormatEntity::Entry::Definition *parent, 1910b9c1b51eSKate Stone FormatEntity::Entry &entry) { 191197206d57SZachary Turner Status error; 1912554f68d3SGreg Clayton 1913554f68d3SGreg Clayton const size_t sep_pos = format_str.find_first_of(".[:"); 1914b9c1b51eSKate Stone const char sep_char = 1915b9c1b51eSKate Stone (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1916554f68d3SGreg Clayton llvm::StringRef key = format_str.substr(0, sep_pos); 1917554f68d3SGreg Clayton 1918554f68d3SGreg Clayton const size_t n = parent->num_children; 1919b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1920554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1921b9c1b51eSKate Stone if (key.equals(entry_def->name) || entry_def->name[0] == '*') { 1922554f68d3SGreg Clayton llvm::StringRef value; 1923554f68d3SGreg Clayton if (sep_char) 1924b9c1b51eSKate Stone value = 1925b9c1b51eSKate Stone format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1926b9c1b51eSKate Stone switch (entry_def->type) { 1927554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentString: 19283a29f8b9SPavel Labath entry.string = format_str.str(); 1929554f68d3SGreg Clayton return error; // Success 1930554f68d3SGreg Clayton 1931554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentNumber: 1932554f68d3SGreg Clayton entry.number = entry_def->data; 1933554f68d3SGreg Clayton return error; // Success 1934554f68d3SGreg Clayton 1935a33964b5SJonas Devlieghere case FormatEntity::Entry::Type::EscapeCode: 1936554f68d3SGreg Clayton entry.type = entry_def->type; 1937554f68d3SGreg Clayton entry.string = entry_def->string; 1938554f68d3SGreg Clayton return error; // Success 1939554f68d3SGreg Clayton 1940554f68d3SGreg Clayton default: 1941554f68d3SGreg Clayton entry.type = entry_def->type; 1942554f68d3SGreg Clayton break; 1943554f68d3SGreg Clayton } 1944554f68d3SGreg Clayton 1945b9c1b51eSKate Stone if (value.empty()) { 1946b9c1b51eSKate Stone if (entry_def->type == FormatEntity::Entry::Type::Invalid) { 1947b9c1b51eSKate Stone if (entry_def->children) { 1948554f68d3SGreg Clayton StreamString error_strm; 1949b9c1b51eSKate Stone error_strm.Printf("'%s' can't be specified on its own, you must " 1950b9c1b51eSKate Stone "access one of its children: ", 1951b9c1b51eSKate Stone entry_def->name); 1952554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, entry_def); 1953c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1954b9c1b51eSKate Stone } else if (sep_char == ':') { 1955b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 195605097246SAdrian Prantl // string argument that needs to be stored in the entry (like 195705097246SAdrian Prantl // "${script.var:}"). In this case the string value is the empty 195805097246SAdrian Prantl // string which is ok. 1959b9c1b51eSKate Stone } else { 1960554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1961554f68d3SGreg Clayton } 1962554f68d3SGreg Clayton } 1963b9c1b51eSKate Stone } else { 1964b9c1b51eSKate Stone if (entry_def->children) { 1965554f68d3SGreg Clayton error = ParseEntry(value, entry_def, entry); 1966b9c1b51eSKate Stone } else if (sep_char == ':') { 1967b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 196805097246SAdrian Prantl // string argument that needs to be stored in the entry (like 1969b9c1b51eSKate Stone // "${script.var:modulename.function}") 19703a29f8b9SPavel Labath entry.string = value.str(); 1971b9c1b51eSKate Stone } else { 1972b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1973b9c1b51eSKate Stone "'%s' followed by '%s' but it has no children", key.str().c_str(), 1974554f68d3SGreg Clayton value.str().c_str()); 1975554f68d3SGreg Clayton } 1976554f68d3SGreg Clayton } 1977554f68d3SGreg Clayton return error; 1978554f68d3SGreg Clayton } 1979554f68d3SGreg Clayton } 1980554f68d3SGreg Clayton StreamString error_strm; 1981554f68d3SGreg Clayton if (parent->type == FormatEntity::Entry::Type::Root) 1982b9c1b51eSKate Stone error_strm.Printf( 1983b9c1b51eSKate Stone "invalid top level item '%s'. Valid top level items are: ", 1984b9c1b51eSKate Stone key.str().c_str()); 1985554f68d3SGreg Clayton else 1986b9c1b51eSKate Stone error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", 1987b9c1b51eSKate Stone key.str().c_str(), parent->name); 1988554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, parent); 1989c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1990554f68d3SGreg Clayton return error; 1991554f68d3SGreg Clayton } 1992554f68d3SGreg Clayton 1993554f68d3SGreg Clayton static const FormatEntity::Entry::Definition * 1994b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str, 1995b9c1b51eSKate Stone const FormatEntity::Entry::Definition *parent, 1996b9c1b51eSKate Stone llvm::StringRef &remainder) { 199797206d57SZachary Turner Status error; 1998554f68d3SGreg Clayton 1999554f68d3SGreg Clayton std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 2000554f68d3SGreg Clayton const size_t n = parent->num_children; 2001b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 2002554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 2003b9c1b51eSKate Stone if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { 2004b9c1b51eSKate Stone if (p.second.empty()) { 2005554f68d3SGreg Clayton if (format_str.back() == '.') 2006554f68d3SGreg Clayton remainder = format_str.drop_front(format_str.size() - 1); 2007554f68d3SGreg Clayton else 2008554f68d3SGreg Clayton remainder = llvm::StringRef(); // Exact match 2009554f68d3SGreg Clayton return entry_def; 2010b9c1b51eSKate Stone } else { 2011b9c1b51eSKate Stone if (entry_def->children) { 2012554f68d3SGreg Clayton return FindEntry(p.second, entry_def, remainder); 2013b9c1b51eSKate Stone } else { 2014554f68d3SGreg Clayton remainder = p.second; 2015554f68d3SGreg Clayton return entry_def; 2016554f68d3SGreg Clayton } 2017554f68d3SGreg Clayton } 2018554f68d3SGreg Clayton } 2019554f68d3SGreg Clayton } 2020554f68d3SGreg Clayton remainder = format_str; 2021554f68d3SGreg Clayton return parent; 2022554f68d3SGreg Clayton } 2023554f68d3SGreg Clayton 202497206d57SZachary Turner Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, 2025b9c1b51eSKate Stone uint32_t depth) { 202697206d57SZachary Turner Status error; 2027b9c1b51eSKate Stone while (!format.empty() && error.Success()) { 2028554f68d3SGreg Clayton const size_t non_special_chars = format.find_first_of("${}\\"); 2029554f68d3SGreg Clayton 2030b9c1b51eSKate Stone if (non_special_chars == llvm::StringRef::npos) { 2031554f68d3SGreg Clayton // No special characters, just string bytes so add them and we are done 2032554f68d3SGreg Clayton parent_entry.AppendText(format); 2033554f68d3SGreg Clayton return error; 2034554f68d3SGreg Clayton } 2035554f68d3SGreg Clayton 2036b9c1b51eSKate Stone if (non_special_chars > 0) { 2037b9c1b51eSKate Stone // We have a special character, so add all characters before these as a 2038b9c1b51eSKate Stone // plain string 2039554f68d3SGreg Clayton parent_entry.AppendText(format.substr(0, non_special_chars)); 2040554f68d3SGreg Clayton format = format.drop_front(non_special_chars); 2041554f68d3SGreg Clayton } 2042554f68d3SGreg Clayton 2043b9c1b51eSKate Stone switch (format[0]) { 2044554f68d3SGreg Clayton case '\0': 2045554f68d3SGreg Clayton return error; 2046554f68d3SGreg Clayton 2047b9c1b51eSKate Stone case '{': { 2048554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2049554f68d3SGreg Clayton Entry scope_entry(Entry::Type::Scope); 2050554f68d3SGreg Clayton error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); 2051554f68d3SGreg Clayton if (error.Fail()) 2052554f68d3SGreg Clayton return error; 2053554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(scope_entry)); 2054b9c1b51eSKate Stone } break; 2055554f68d3SGreg Clayton 2056554f68d3SGreg Clayton case '}': 2057554f68d3SGreg Clayton if (depth == 0) 2058554f68d3SGreg Clayton error.SetErrorString("unmatched '}' character"); 2059554f68d3SGreg Clayton else 2060b9c1b51eSKate Stone format = 2061b9c1b51eSKate Stone format 2062b9c1b51eSKate Stone .drop_front(); // Skip the '}' as we are at the end of the scope 2063554f68d3SGreg Clayton return error; 2064554f68d3SGreg Clayton 2065b9c1b51eSKate Stone case '\\': { 2066554f68d3SGreg Clayton format = format.drop_front(); // Skip the '\' character 2067b9c1b51eSKate Stone if (format.empty()) { 2068b9c1b51eSKate Stone error.SetErrorString( 2069b9c1b51eSKate Stone "'\\' character was not followed by another character"); 2070554f68d3SGreg Clayton return error; 2071554f68d3SGreg Clayton } 2072554f68d3SGreg Clayton 2073554f68d3SGreg Clayton const char desens_char = format[0]; 2074554f68d3SGreg Clayton format = format.drop_front(); // Skip the desensitized char character 2075b9c1b51eSKate Stone switch (desens_char) { 2076b9c1b51eSKate Stone case 'a': 2077b9c1b51eSKate Stone parent_entry.AppendChar('\a'); 2078b9c1b51eSKate Stone break; 2079b9c1b51eSKate Stone case 'b': 2080b9c1b51eSKate Stone parent_entry.AppendChar('\b'); 2081b9c1b51eSKate Stone break; 2082b9c1b51eSKate Stone case 'f': 2083b9c1b51eSKate Stone parent_entry.AppendChar('\f'); 2084b9c1b51eSKate Stone break; 2085b9c1b51eSKate Stone case 'n': 2086b9c1b51eSKate Stone parent_entry.AppendChar('\n'); 2087b9c1b51eSKate Stone break; 2088b9c1b51eSKate Stone case 'r': 2089b9c1b51eSKate Stone parent_entry.AppendChar('\r'); 2090b9c1b51eSKate Stone break; 2091b9c1b51eSKate Stone case 't': 2092b9c1b51eSKate Stone parent_entry.AppendChar('\t'); 2093b9c1b51eSKate Stone break; 2094b9c1b51eSKate Stone case 'v': 2095b9c1b51eSKate Stone parent_entry.AppendChar('\v'); 2096b9c1b51eSKate Stone break; 2097b9c1b51eSKate Stone case '\'': 2098b9c1b51eSKate Stone parent_entry.AppendChar('\''); 2099b9c1b51eSKate Stone break; 2100b9c1b51eSKate Stone case '\\': 2101b9c1b51eSKate Stone parent_entry.AppendChar('\\'); 2102b9c1b51eSKate Stone break; 2103554f68d3SGreg Clayton case '0': 2104554f68d3SGreg Clayton // 1 to 3 octal chars 2105554f68d3SGreg Clayton { 210605097246SAdrian Prantl // Make a string that can hold onto the initial zero char, up to 3 210705097246SAdrian Prantl // octal digits, and a terminating NULL. 2108554f68d3SGreg Clayton char oct_str[5] = {0, 0, 0, 0, 0}; 2109554f68d3SGreg Clayton 2110554f68d3SGreg Clayton int i; 2111554f68d3SGreg Clayton for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) 2112554f68d3SGreg Clayton oct_str[i] = format[i]; 2113554f68d3SGreg Clayton 211405097246SAdrian Prantl // We don't want to consume the last octal character since the main 211505097246SAdrian Prantl // for loop will do this for us, so we advance p by one less than i 211605097246SAdrian Prantl // (even if i is zero) 2117554f68d3SGreg Clayton format = format.drop_front(i); 2118a74f37a5SEugene Zelenko unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); 2119b9c1b51eSKate Stone if (octal_value <= UINT8_MAX) { 2120554f68d3SGreg Clayton parent_entry.AppendChar((char)octal_value); 2121b9c1b51eSKate Stone } else { 2122554f68d3SGreg Clayton error.SetErrorString("octal number is larger than a single byte"); 2123554f68d3SGreg Clayton return error; 2124554f68d3SGreg Clayton } 2125554f68d3SGreg Clayton } 2126554f68d3SGreg Clayton break; 2127554f68d3SGreg Clayton 2128554f68d3SGreg Clayton case 'x': 2129554f68d3SGreg Clayton // hex number in the format 2130b9c1b51eSKate Stone if (isxdigit(format[0])) { 2131554f68d3SGreg Clayton // Make a string that can hold onto two hex chars plus a 2132554f68d3SGreg Clayton // NULL terminator 2133554f68d3SGreg Clayton char hex_str[3] = {0, 0, 0}; 2134554f68d3SGreg Clayton hex_str[0] = format[0]; 2135554f68d3SGreg Clayton 2136554f68d3SGreg Clayton format = format.drop_front(); 2137554f68d3SGreg Clayton 2138b9c1b51eSKate Stone if (isxdigit(format[0])) { 2139554f68d3SGreg Clayton hex_str[1] = format[0]; 2140554f68d3SGreg Clayton format = format.drop_front(); 2141554f68d3SGreg Clayton } 2142554f68d3SGreg Clayton 2143a74f37a5SEugene Zelenko unsigned long hex_value = strtoul(hex_str, nullptr, 16); 2144b9c1b51eSKate Stone if (hex_value <= UINT8_MAX) { 2145554f68d3SGreg Clayton parent_entry.AppendChar((char)hex_value); 2146b9c1b51eSKate Stone } else { 2147554f68d3SGreg Clayton error.SetErrorString("hex number is larger than a single byte"); 2148554f68d3SGreg Clayton return error; 2149554f68d3SGreg Clayton } 2150b9c1b51eSKate Stone } else { 2151554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2152554f68d3SGreg Clayton } 2153554f68d3SGreg Clayton break; 2154554f68d3SGreg Clayton 2155554f68d3SGreg Clayton default: 215605097246SAdrian Prantl // Just desensitize any other character by just printing what came 215705097246SAdrian Prantl // after the '\' 2158554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2159554f68d3SGreg Clayton break; 2160554f68d3SGreg Clayton } 2161b9c1b51eSKate Stone } break; 2162554f68d3SGreg Clayton 2163554f68d3SGreg Clayton case '$': 2164b9c1b51eSKate Stone if (format.size() == 1) { 2165554f68d3SGreg Clayton // '$' at the end of a format string, just print the '$' 2166554f68d3SGreg Clayton parent_entry.AppendText("$"); 2167b9c1b51eSKate Stone } else { 2168554f68d3SGreg Clayton format = format.drop_front(); // Skip the '$' 2169554f68d3SGreg Clayton 2170b9c1b51eSKate Stone if (format[0] == '{') { 2171554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2172554f68d3SGreg Clayton 2173554f68d3SGreg Clayton llvm::StringRef variable, variable_format; 2174b9c1b51eSKate Stone error = FormatEntity::ExtractVariableInfo(format, variable, 2175b9c1b51eSKate Stone variable_format); 2176554f68d3SGreg Clayton if (error.Fail()) 2177554f68d3SGreg Clayton return error; 2178554f68d3SGreg Clayton bool verify_is_thread_id = false; 2179554f68d3SGreg Clayton Entry entry; 2180b9c1b51eSKate Stone if (!variable_format.empty()) { 21813a29f8b9SPavel Labath entry.printf_format = variable_format.str(); 2182554f68d3SGreg Clayton 218305097246SAdrian Prantl // If the format contains a '%' we are going to assume this is a 218405097246SAdrian Prantl // printf style format. So if you want to format your thread ID 218505097246SAdrian Prantl // using "0x%llx" you can use: ${thread.id%0x%llx} 2186554f68d3SGreg Clayton // 2187554f68d3SGreg Clayton // If there is no '%' in the format, then it is assumed to be a 2188554f68d3SGreg Clayton // LLDB format name, or one of the extended formats specified in 2189554f68d3SGreg Clayton // the switch statement below. 2190554f68d3SGreg Clayton 2191b9c1b51eSKate Stone if (entry.printf_format.find('%') == std::string::npos) { 2192554f68d3SGreg Clayton bool clear_printf = false; 2193554f68d3SGreg Clayton 2194b9c1b51eSKate Stone if (FormatManager::GetFormatFromCString( 2195b9c1b51eSKate Stone entry.printf_format.c_str(), false, entry.fmt)) { 2196554f68d3SGreg Clayton // We have an LLDB format, so clear the printf format 2197554f68d3SGreg Clayton clear_printf = true; 2198b9c1b51eSKate Stone } else if (entry.printf_format.size() == 1) { 2199b9c1b51eSKate Stone switch (entry.printf_format[0]) { 2200554f68d3SGreg Clayton case '@': // if this is an @ sign, print ObjC description 2201b9c1b51eSKate Stone entry.number = ValueObject:: 2202b9c1b51eSKate Stone eValueObjectRepresentationStyleLanguageSpecific; 2203554f68d3SGreg Clayton clear_printf = true; 2204554f68d3SGreg Clayton break; 2205b9c1b51eSKate Stone case 'V': // if this is a V, print the value using the default 2206b9c1b51eSKate Stone // format 2207b9c1b51eSKate Stone entry.number = 2208b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2209554f68d3SGreg Clayton clear_printf = true; 2210554f68d3SGreg Clayton break; 2211554f68d3SGreg Clayton case 'L': // if this is an L, print the location of the value 2212b9c1b51eSKate Stone entry.number = 2213b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleLocation; 2214554f68d3SGreg Clayton clear_printf = true; 2215554f68d3SGreg Clayton break; 2216554f68d3SGreg Clayton case 'S': // if this is an S, print the summary after all 2217b9c1b51eSKate Stone entry.number = 2218b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2219554f68d3SGreg Clayton clear_printf = true; 2220554f68d3SGreg Clayton break; 2221554f68d3SGreg Clayton case '#': // if this is a '#', print the number of children 2222b9c1b51eSKate Stone entry.number = 2223b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleChildrenCount; 2224554f68d3SGreg Clayton clear_printf = true; 2225554f68d3SGreg Clayton break; 2226554f68d3SGreg Clayton case 'T': // if this is a 'T', print the type 2227b9c1b51eSKate Stone entry.number = 2228b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleType; 2229554f68d3SGreg Clayton clear_printf = true; 2230554f68d3SGreg Clayton break; 2231554f68d3SGreg Clayton case 'N': // if this is a 'N', print the name 2232b9c1b51eSKate Stone entry.number = 2233b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleName; 2234554f68d3SGreg Clayton clear_printf = true; 2235554f68d3SGreg Clayton break; 2236281b65bcSGreg Clayton case '>': // if this is a '>', print the expression path 2237b9c1b51eSKate Stone entry.number = ValueObject:: 2238b9c1b51eSKate Stone eValueObjectRepresentationStyleExpressionPath; 2239554f68d3SGreg Clayton clear_printf = true; 2240554f68d3SGreg Clayton break; 2241554f68d3SGreg Clayton default: 2242b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2243b9c1b51eSKate Stone entry.printf_format.c_str()); 2244554f68d3SGreg Clayton return error; 2245554f68d3SGreg Clayton } 2246b9c1b51eSKate Stone } else if (FormatManager::GetFormatFromCString( 2247b9c1b51eSKate Stone entry.printf_format.c_str(), true, entry.fmt)) { 2248554f68d3SGreg Clayton clear_printf = true; 2249b9c1b51eSKate Stone } else if (entry.printf_format == "tid") { 2250554f68d3SGreg Clayton verify_is_thread_id = true; 2251b9c1b51eSKate Stone } else { 2252b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2253b9c1b51eSKate Stone entry.printf_format.c_str()); 2254554f68d3SGreg Clayton return error; 2255554f68d3SGreg Clayton } 2256554f68d3SGreg Clayton 2257554f68d3SGreg Clayton // Our format string turned out to not be a printf style format 2258554f68d3SGreg Clayton // so lets clear the string 2259554f68d3SGreg Clayton if (clear_printf) 2260554f68d3SGreg Clayton entry.printf_format.clear(); 2261554f68d3SGreg Clayton } 2262554f68d3SGreg Clayton } 2263554f68d3SGreg Clayton 2264554f68d3SGreg Clayton // Check for dereferences 2265b9c1b51eSKate Stone if (variable[0] == '*') { 2266554f68d3SGreg Clayton entry.deref = true; 2267554f68d3SGreg Clayton variable = variable.drop_front(); 2268554f68d3SGreg Clayton } 2269554f68d3SGreg Clayton 2270554f68d3SGreg Clayton error = ParseEntry(variable, &g_root, entry); 2271554f68d3SGreg Clayton if (error.Fail()) 2272554f68d3SGreg Clayton return error; 2273554f68d3SGreg Clayton 2274b9c1b51eSKate Stone if (verify_is_thread_id) { 2275554f68d3SGreg Clayton if (entry.type != Entry::Type::ThreadID && 2276b9c1b51eSKate Stone entry.type != Entry::Type::ThreadProtocolID) { 2277b9c1b51eSKate Stone error.SetErrorString("the 'tid' format can only be used on " 2278b9c1b51eSKate Stone "${thread.id} and ${thread.protocol_id}"); 2279554f68d3SGreg Clayton } 2280554f68d3SGreg Clayton } 2281554f68d3SGreg Clayton 2282b9c1b51eSKate Stone switch (entry.type) { 2283554f68d3SGreg Clayton case Entry::Type::Variable: 2284554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 2285b9c1b51eSKate Stone if (entry.number == 0) { 2286554f68d3SGreg Clayton if (entry.string.empty()) 2287b9c1b51eSKate Stone entry.number = 2288b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2289554f68d3SGreg Clayton else 2290b9c1b51eSKate Stone entry.number = 2291b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2292554f68d3SGreg Clayton } 2293554f68d3SGreg Clayton break; 2294554f68d3SGreg Clayton default: 2295b9c1b51eSKate Stone // Make sure someone didn't try to dereference anything but ${var} 2296b9c1b51eSKate Stone // or ${svar} 2297b9c1b51eSKate Stone if (entry.deref) { 2298b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2299b9c1b51eSKate Stone "${%s} can't be dereferenced, only ${var} and ${svar} can.", 2300b9c1b51eSKate Stone variable.str().c_str()); 2301554f68d3SGreg Clayton return error; 2302554f68d3SGreg Clayton } 2303554f68d3SGreg Clayton } 2304554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(entry)); 2305554f68d3SGreg Clayton } 2306554f68d3SGreg Clayton } 2307554f68d3SGreg Clayton break; 2308554f68d3SGreg Clayton } 2309554f68d3SGreg Clayton } 2310554f68d3SGreg Clayton return error; 2311554f68d3SGreg Clayton } 2312554f68d3SGreg Clayton 231397206d57SZachary Turner Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, 2314b9c1b51eSKate Stone llvm::StringRef &variable_name, 2315b9c1b51eSKate Stone llvm::StringRef &variable_format) { 231697206d57SZachary Turner Status error; 2317554f68d3SGreg Clayton variable_name = llvm::StringRef(); 2318554f68d3SGreg Clayton variable_format = llvm::StringRef(); 2319554f68d3SGreg Clayton 2320e8433cc1SBruce Mitchener const size_t paren_pos = format_str.find('}'); 2321b9c1b51eSKate Stone if (paren_pos != llvm::StringRef::npos) { 2322e8433cc1SBruce Mitchener const size_t percent_pos = format_str.find('%'); 2323b9c1b51eSKate Stone if (percent_pos < paren_pos) { 2324b9c1b51eSKate Stone if (percent_pos > 0) { 2325554f68d3SGreg Clayton if (percent_pos > 1) 2326554f68d3SGreg Clayton variable_name = format_str.substr(0, percent_pos); 2327b9c1b51eSKate Stone variable_format = 2328b9c1b51eSKate Stone format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2329554f68d3SGreg Clayton } 2330b9c1b51eSKate Stone } else { 2331554f68d3SGreg Clayton variable_name = format_str.substr(0, paren_pos); 2332554f68d3SGreg Clayton } 2333554f68d3SGreg Clayton // Strip off elements and the formatting and the trailing '}' 2334554f68d3SGreg Clayton format_str = format_str.substr(paren_pos + 1); 2335b9c1b51eSKate Stone } else { 2336b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2337b9c1b51eSKate Stone "missing terminating '}' character for '${%s'", 2338b9c1b51eSKate Stone format_str.str().c_str()); 2339554f68d3SGreg Clayton } 2340554f68d3SGreg Clayton return error; 2341554f68d3SGreg Clayton } 2342554f68d3SGreg Clayton 2343b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, 2344b9c1b51eSKate Stone llvm::StringRef variable_name, 2345b9c1b51eSKate Stone llvm::StringRef variable_format) { 2346b9c1b51eSKate Stone if (variable_name.empty() || variable_name.equals(".fullpath")) { 23474dac97ebSRaphael Isemann file_spec.Dump(s.AsRawOstream()); 2348554f68d3SGreg Clayton return true; 2349b9c1b51eSKate Stone } else if (variable_name.equals(".basename")) { 2350642bc15dSRaphael Isemann s.PutCString(file_spec.GetFilename().GetStringRef()); 2351554f68d3SGreg Clayton return true; 2352b9c1b51eSKate Stone } else if (variable_name.equals(".dirname")) { 2353642bc15dSRaphael Isemann s.PutCString(file_spec.GetFilename().GetStringRef()); 2354554f68d3SGreg Clayton return true; 2355554f68d3SGreg Clayton } 2356554f68d3SGreg Clayton return false; 2357554f68d3SGreg Clayton } 2358554f68d3SGreg Clayton 2359b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix, 2360b9c1b51eSKate Stone const char *suffix) { 2361554f68d3SGreg Clayton std::string match(prefix.str()); 2362554f68d3SGreg Clayton match.append(suffix); 23633a29f8b9SPavel Labath return match; 2364554f68d3SGreg Clayton } 2365554f68d3SGreg Clayton 2366b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def, 2367554f68d3SGreg Clayton const llvm::StringRef &prefix, 2368554f68d3SGreg Clayton const llvm::StringRef &match_prefix, 2369b9c1b51eSKate Stone StringList &matches) { 2370554f68d3SGreg Clayton const size_t n = def->num_children; 2371b9c1b51eSKate Stone if (n > 0) { 2372b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 23733a29f8b9SPavel Labath std::string match = prefix.str(); 2374554f68d3SGreg Clayton if (match_prefix.empty()) 2375554f68d3SGreg Clayton matches.AppendString(MakeMatch(prefix, def->children[i].name)); 2376b9c1b51eSKate Stone else if (strncmp(def->children[i].name, match_prefix.data(), 2377b9c1b51eSKate Stone match_prefix.size()) == 0) 2378b9c1b51eSKate Stone matches.AppendString( 2379b9c1b51eSKate Stone MakeMatch(prefix, def->children[i].name + match_prefix.size())); 2380554f68d3SGreg Clayton } 2381554f68d3SGreg Clayton } 2382554f68d3SGreg Clayton } 2383a74f37a5SEugene Zelenko 2384ae34ed2cSRaphael Isemann void FormatEntity::AutoComplete(CompletionRequest &request) { 23858b0d15e4SMatthias Gehre llvm::StringRef str = request.GetCursorArgumentPrefix(); 2386a2e76c0bSRaphael Isemann 2387554f68d3SGreg Clayton const size_t dollar_pos = str.rfind('$'); 23884aa8753cSZachary Turner if (dollar_pos == llvm::StringRef::npos) 2389ae34ed2cSRaphael Isemann return; 23904aa8753cSZachary Turner 2391554f68d3SGreg Clayton // Hitting TAB after $ at the end of the string add a "{" 2392b9c1b51eSKate Stone if (dollar_pos == str.size() - 1) { 23933a29f8b9SPavel Labath std::string match = str.str(); 2394554f68d3SGreg Clayton match.append("{"); 23951a6d7ab5SRaphael Isemann request.AddCompletion(match); 2396ae34ed2cSRaphael Isemann return; 23974aa8753cSZachary Turner } 23984aa8753cSZachary Turner 23994aa8753cSZachary Turner if (str[dollar_pos + 1] != '{') 2400ae34ed2cSRaphael Isemann return; 24014aa8753cSZachary Turner 2402554f68d3SGreg Clayton const size_t close_pos = str.find('}', dollar_pos + 2); 24034aa8753cSZachary Turner if (close_pos != llvm::StringRef::npos) 2404ae34ed2cSRaphael Isemann return; 24054aa8753cSZachary Turner 2406554f68d3SGreg Clayton const size_t format_pos = str.find('%', dollar_pos + 2); 24074aa8753cSZachary Turner if (format_pos != llvm::StringRef::npos) 2408ae34ed2cSRaphael Isemann return; 24094aa8753cSZachary Turner 2410554f68d3SGreg Clayton llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); 2411b9c1b51eSKate Stone if (partial_variable.empty()) { 2412e9264b74SKazuaki Ishizaki // Suggest all top level entities as we are just past "${" 24131a6d7ab5SRaphael Isemann StringList new_matches; 24141a6d7ab5SRaphael Isemann AddMatches(&g_root, str, llvm::StringRef(), new_matches); 24151a6d7ab5SRaphael Isemann request.AddCompletions(new_matches); 2416ae34ed2cSRaphael Isemann return; 24174aa8753cSZachary Turner } 24184aa8753cSZachary Turner 2419554f68d3SGreg Clayton // We have a partially specified variable, find it 2420554f68d3SGreg Clayton llvm::StringRef remainder; 2421b9c1b51eSKate Stone const FormatEntity::Entry::Definition *entry_def = 2422b9c1b51eSKate Stone FindEntry(partial_variable, &g_root, remainder); 24234aa8753cSZachary Turner if (!entry_def) 2424ae34ed2cSRaphael Isemann return; 24254aa8753cSZachary Turner 2426554f68d3SGreg Clayton const size_t n = entry_def->num_children; 2427554f68d3SGreg Clayton 2428b9c1b51eSKate Stone if (remainder.empty()) { 2429554f68d3SGreg Clayton // Exact match 2430b9c1b51eSKate Stone if (n > 0) { 2431554f68d3SGreg Clayton // "${thread.info" <TAB> 24321a6d7ab5SRaphael Isemann request.AddCompletion(MakeMatch(str, ".")); 2433b9c1b51eSKate Stone } else { 2434554f68d3SGreg Clayton // "${thread.id" <TAB> 24351a6d7ab5SRaphael Isemann request.AddCompletion(MakeMatch(str, "}")); 2436554f68d3SGreg Clayton } 2437b9c1b51eSKate Stone } else if (remainder.equals(".")) { 2438554f68d3SGreg Clayton // "${thread." <TAB> 24391a6d7ab5SRaphael Isemann StringList new_matches; 24401a6d7ab5SRaphael Isemann AddMatches(entry_def, str, llvm::StringRef(), new_matches); 24411a6d7ab5SRaphael Isemann request.AddCompletions(new_matches); 2442b9c1b51eSKate Stone } else { 2443554f68d3SGreg Clayton // We have a partial match 2444554f68d3SGreg Clayton // "${thre" <TAB> 24451a6d7ab5SRaphael Isemann StringList new_matches; 24461a6d7ab5SRaphael Isemann AddMatches(entry_def, str, remainder, new_matches); 24471a6d7ab5SRaphael Isemann request.AddCompletions(new_matches); 2448554f68d3SGreg Clayton } 2449554f68d3SGreg Clayton } 2450