1554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===// 2554f68d3SGreg Clayton // 3554f68d3SGreg Clayton // The LLVM Compiler Infrastructure 4554f68d3SGreg Clayton // 5554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source 6554f68d3SGreg Clayton // License. See LICENSE.TXT for details. 7554f68d3SGreg Clayton // 8554f68d3SGreg Clayton //===----------------------------------------------------------------------===// 9554f68d3SGreg Clayton 10554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 11554f68d3SGreg Clayton 12a74f37a5SEugene Zelenko // C Includes 13a74f37a5SEugene Zelenko // C++ Includes 14a74f37a5SEugene Zelenko // Other libraries and framework includes 15d717cc9fSEnrico Granata #include "llvm/ADT/STLExtras.h" 16d717cc9fSEnrico Granata #include "llvm/ADT/StringRef.h" 17d717cc9fSEnrico Granata 18a74f37a5SEugene Zelenko // Project includes 19554f68d3SGreg Clayton #include "lldb/Core/Address.h" 20554f68d3SGreg Clayton #include "lldb/Core/Debugger.h" 21554f68d3SGreg Clayton #include "lldb/Core/Module.h" 22554f68d3SGreg Clayton #include "lldb/Core/Stream.h" 23554f68d3SGreg Clayton #include "lldb/Core/StreamString.h" 24554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h" 25554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 26554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h" 27554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h" 28ad91c7ceSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h" 29937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h" 30554f68d3SGreg Clayton #include "lldb/Host/FileSpec.h" 31554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 32554f68d3SGreg Clayton #include "lldb/Symbol/Block.h" 33554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 34554f68d3SGreg Clayton #include "lldb/Symbol/Function.h" 35554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h" 36554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h" 37554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h" 38554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h" 390e0984eeSJim Ingham #include "lldb/Target/Language.h" 40554f68d3SGreg Clayton #include "lldb/Target/Process.h" 41554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h" 42554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h" 43554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h" 44554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h" 45554f68d3SGreg Clayton #include "lldb/Target/Target.h" 46554f68d3SGreg Clayton #include "lldb/Target/Thread.h" 47554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 48554f68d3SGreg Clayton 49554f68d3SGreg Clayton using namespace lldb; 50554f68d3SGreg Clayton using namespace lldb_private; 51554f68d3SGreg Clayton 52b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath }; 53554f68d3SGreg Clayton 54b9c1b51eSKate Stone #define ENTRY(n, t, f) \ 55b9c1b51eSKate Stone { \ 56b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 57b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false \ 58b9c1b51eSKate Stone } 59b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v) \ 60b9c1b51eSKate Stone { \ 61b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 62b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, v, 0, nullptr, false \ 63b9c1b51eSKate Stone } 64b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c) \ 65b9c1b51eSKate Stone { \ 66b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 67b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \ 68b9c1b51eSKate Stone false \ 69b9c1b51eSKate Stone } 70b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \ 71b9c1b51eSKate Stone { \ 72b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 73b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \ 74b9c1b51eSKate Stone true \ 75b9c1b51eSKate Stone } 76b9c1b51eSKate Stone #define ENTRY_STRING(n, s) \ 77b9c1b51eSKate Stone { \ 78b9c1b51eSKate Stone n, s, FormatEntity::Entry::Type::InsertString, \ 79b9c1b51eSKate Stone FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false \ 80b9c1b51eSKate Stone } 81b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = { 82b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 83554f68d3SGreg Clayton 84b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = { 85b9c1b51eSKate Stone ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64), 86554f68d3SGreg Clayton ENTRY("load", AddressLoadOrFile, UInt64), 87554f68d3SGreg Clayton }; 88554f68d3SGreg Clayton 89b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = { 90554f68d3SGreg Clayton ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), 91554f68d3SGreg Clayton ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), 92b9c1b51eSKate Stone ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)}; 93554f68d3SGreg Clayton 94b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = { 95554f68d3SGreg Clayton ENTRY("index", FrameIndex, UInt32), 96554f68d3SGreg Clayton ENTRY("pc", FrameRegisterPC, UInt64), 97554f68d3SGreg Clayton ENTRY("fp", FrameRegisterFP, UInt64), 98554f68d3SGreg Clayton ENTRY("sp", FrameRegisterSP, UInt64), 99554f68d3SGreg Clayton ENTRY("flags", FrameRegisterFlags, UInt64), 100554f68d3SGreg Clayton ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), 101554f68d3SGreg Clayton }; 102554f68d3SGreg Clayton 103b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = { 104b9c1b51eSKate Stone ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString), 105554f68d3SGreg Clayton ENTRY("name-without-args", FunctionNameNoArgs, CString), 106554f68d3SGreg Clayton ENTRY("name-with-args", FunctionNameWithArgs, CString), 107554f68d3SGreg Clayton ENTRY("addr-offset", FunctionAddrOffset, UInt64), 108b9c1b51eSKate Stone ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, 109b9c1b51eSKate Stone UInt64), 110554f68d3SGreg Clayton ENTRY("line-offset", FunctionLineOffset, UInt64), 111c980fa92SJason Molenda ENTRY("pc-offset", FunctionPCOffset, UInt64), 112c980fa92SJason Molenda ENTRY("initial-function", FunctionInitial, None), 1136ab659a9SJason Molenda ENTRY("changed", FunctionChanged, None), 114b9c1b51eSKate Stone ENTRY("is-optimized", FunctionIsOptimized, None)}; 115554f68d3SGreg Clayton 116b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = { 117554f68d3SGreg Clayton ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), 118554f68d3SGreg Clayton ENTRY("number", LineEntryLineNumber, UInt32), 119554f68d3SGreg Clayton ENTRY("start-addr", LineEntryStartAddress, UInt64), 120554f68d3SGreg Clayton ENTRY("end-addr", LineEntryEndAddress, UInt64), 121554f68d3SGreg Clayton }; 122554f68d3SGreg Clayton 123b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = { 124554f68d3SGreg Clayton ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), 125554f68d3SGreg Clayton }; 126554f68d3SGreg Clayton 127b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = { 128554f68d3SGreg Clayton ENTRY("id", ProcessID, UInt64), 129554f68d3SGreg Clayton ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename), 130554f68d3SGreg Clayton ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries), 131554f68d3SGreg Clayton }; 132554f68d3SGreg Clayton 133b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = { 134b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 135554f68d3SGreg Clayton 136b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = { 137b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 138554f68d3SGreg Clayton 139b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = { 140554f68d3SGreg Clayton ENTRY("id", ThreadID, UInt64), 141554f68d3SGreg Clayton ENTRY("protocol_id", ThreadProtocolID, UInt64), 142554f68d3SGreg Clayton ENTRY("index", ThreadIndexID, UInt32), 143554f68d3SGreg Clayton ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry), 144554f68d3SGreg Clayton ENTRY("queue", ThreadQueue, CString), 145554f68d3SGreg Clayton ENTRY("name", ThreadName, CString), 146554f68d3SGreg Clayton ENTRY("stop-reason", ThreadStopReason, CString), 147554f68d3SGreg Clayton ENTRY("return-value", ThreadReturnValue, CString), 148554f68d3SGreg Clayton ENTRY("completed-expression", ThreadCompletedExpression, CString), 149554f68d3SGreg Clayton }; 150554f68d3SGreg Clayton 151b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = { 152554f68d3SGreg Clayton ENTRY("arch", TargetArch, CString), 153554f68d3SGreg Clayton }; 154554f68d3SGreg Clayton 155554f68d3SGreg Clayton #define _TO_STR2(_val) #_val 156554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val) 157554f68d3SGreg Clayton 158b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { 159b9c1b51eSKate Stone ENTRY_STRING("black", 160b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 161554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 162b9c1b51eSKate Stone ENTRY_STRING("green", 163b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 164b9c1b51eSKate Stone ENTRY_STRING("yellow", 165b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 166b9c1b51eSKate Stone ENTRY_STRING("blue", 167b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 168b9c1b51eSKate Stone ENTRY_STRING("purple", 169b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 170b9c1b51eSKate Stone ENTRY_STRING("cyan", 171b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 172b9c1b51eSKate Stone ENTRY_STRING("white", 173b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 174554f68d3SGreg Clayton }; 175554f68d3SGreg Clayton 176b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { 177b9c1b51eSKate Stone ENTRY_STRING("black", 178b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 179554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 180b9c1b51eSKate Stone ENTRY_STRING("green", 181b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 182b9c1b51eSKate Stone ENTRY_STRING("yellow", 183b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 184b9c1b51eSKate Stone ENTRY_STRING("blue", 185b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 186b9c1b51eSKate Stone ENTRY_STRING("purple", 187b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 188b9c1b51eSKate Stone ENTRY_STRING("cyan", 189b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 190b9c1b51eSKate Stone ENTRY_STRING("white", 191b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 192554f68d3SGreg Clayton }; 193554f68d3SGreg Clayton 194b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = { 195554f68d3SGreg Clayton ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries), 196554f68d3SGreg Clayton ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries), 197b9c1b51eSKate Stone ENTRY_STRING("normal", 198b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 199554f68d3SGreg Clayton ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 200554f68d3SGreg Clayton ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 201b9c1b51eSKate Stone ENTRY_STRING("italic", 202b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 203b9c1b51eSKate Stone ENTRY_STRING("underline", 204b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 205b9c1b51eSKate Stone ENTRY_STRING("slow-blink", 206b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 207b9c1b51eSKate Stone ENTRY_STRING("fast-blink", 208b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 209b9c1b51eSKate Stone ENTRY_STRING("negative", 210b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 211b9c1b51eSKate Stone ENTRY_STRING("conceal", 212b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 213b9c1b51eSKate Stone ENTRY_STRING("crossed-out", 214b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 215554f68d3SGreg Clayton }; 216554f68d3SGreg Clayton 217b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = { 218554f68d3SGreg Clayton ENTRY("frame", ScriptFrame, None), 219554f68d3SGreg Clayton ENTRY("process", ScriptProcess, None), 220554f68d3SGreg Clayton ENTRY("target", ScriptTarget, None), 221554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 222554f68d3SGreg Clayton ENTRY("var", ScriptVariable, None), 223554f68d3SGreg Clayton ENTRY("svar", ScriptVariableSynthetic, None), 224554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 225554f68d3SGreg Clayton }; 226554f68d3SGreg Clayton 227b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = { 228554f68d3SGreg Clayton ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries), 229554f68d3SGreg Clayton ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64), 230554f68d3SGreg Clayton ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries), 231554f68d3SGreg Clayton ENTRY("current-pc-arrow", CurrentPCArrow, CString), 232554f68d3SGreg Clayton ENTRY_CHILDREN("file", File, CString, g_file_child_entries), 233dc975670SDawn Perchik ENTRY("language", Lang, CString), 234554f68d3SGreg Clayton ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries), 235554f68d3SGreg Clayton ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries), 236554f68d3SGreg Clayton ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries), 237554f68d3SGreg Clayton ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries), 238554f68d3SGreg Clayton ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries), 239554f68d3SGreg Clayton ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries), 240b9c1b51eSKate Stone ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None, 241b9c1b51eSKate Stone g_svar_child_entries), 242554f68d3SGreg Clayton ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries), 243554f68d3SGreg Clayton ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries), 244554f68d3SGreg Clayton ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries), 245554f68d3SGreg Clayton }; 246554f68d3SGreg Clayton 247b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root = 248b9c1b51eSKate Stone ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries); 249554f68d3SGreg Clayton 250b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s) 251b9c1b51eSKate Stone : string(s.data(), s.size()), printf_format(), children(), 252b9c1b51eSKate Stone definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), 253b9c1b51eSKate Stone number(0), deref(false) {} 254554f68d3SGreg Clayton 255b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch) 256b9c1b51eSKate Stone : string(1, ch), printf_format(), children(), definition(nullptr), 257b9c1b51eSKate Stone type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} 258554f68d3SGreg Clayton 259b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) { 260554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 261554f68d3SGreg Clayton children.push_back(Entry(ch)); 262554f68d3SGreg Clayton else 263554f68d3SGreg Clayton children.back().string.append(1, ch); 264554f68d3SGreg Clayton } 265554f68d3SGreg Clayton 266b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { 267554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 268554f68d3SGreg Clayton children.push_back(Entry(s)); 269554f68d3SGreg Clayton else 270554f68d3SGreg Clayton children.back().string.append(s.data(), s.size()); 271554f68d3SGreg Clayton } 272554f68d3SGreg Clayton 273b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) { 274554f68d3SGreg Clayton return AppendText(llvm::StringRef(cstr)); 275554f68d3SGreg Clayton } 276554f68d3SGreg Clayton 277b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { 278554f68d3SGreg Clayton entry.Clear(); 279554f68d3SGreg Clayton entry.type = Entry::Type::Root; 280554f68d3SGreg Clayton llvm::StringRef modifiable_format(format_str); 281554f68d3SGreg Clayton return ParseInternal(modifiable_format, entry, 0); 282554f68d3SGreg Clayton } 283554f68d3SGreg Clayton 284b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee) \ 285b9c1b51eSKate Stone case FormatEntity::Entry::Type::eee: \ 286b9c1b51eSKate Stone return #eee 287554f68d3SGreg Clayton 288b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) { 289b9c1b51eSKate Stone switch (t) { 290554f68d3SGreg Clayton ENUM_TO_CSTR(Invalid); 291554f68d3SGreg Clayton ENUM_TO_CSTR(ParentNumber); 292554f68d3SGreg Clayton ENUM_TO_CSTR(ParentString); 293554f68d3SGreg Clayton ENUM_TO_CSTR(InsertString); 294554f68d3SGreg Clayton ENUM_TO_CSTR(Root); 295554f68d3SGreg Clayton ENUM_TO_CSTR(String); 296554f68d3SGreg Clayton ENUM_TO_CSTR(Scope); 297554f68d3SGreg Clayton ENUM_TO_CSTR(Variable); 298554f68d3SGreg Clayton ENUM_TO_CSTR(VariableSynthetic); 299554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariable); 300554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariableSynthetic); 301554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoad); 302554f68d3SGreg Clayton ENUM_TO_CSTR(AddressFile); 303554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoadOrFile); 304554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessID); 305554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessFile); 306554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptProcess); 307554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadID); 308554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadProtocolID); 309554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadIndexID); 310554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadName); 311554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadQueue); 312554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadStopReason); 313554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadReturnValue); 314554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadCompletedExpression); 315554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptThread); 316554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadInfo); 317554f68d3SGreg Clayton ENUM_TO_CSTR(TargetArch); 318554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptTarget); 319554f68d3SGreg Clayton ENUM_TO_CSTR(ModuleFile); 320554f68d3SGreg Clayton ENUM_TO_CSTR(File); 321dc975670SDawn Perchik ENUM_TO_CSTR(Lang); 322554f68d3SGreg Clayton ENUM_TO_CSTR(FrameIndex); 323554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterPC); 324554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterSP); 325554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFP); 326554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFlags); 327554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterByName); 328554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptFrame); 329554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionID); 330554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionDidChange); 331554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionInitialFunction); 332554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionName); 333554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameWithArgs); 334554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameNoArgs); 335554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffset); 336554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 337554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionLineOffset); 338554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionPCOffset); 339c980fa92SJason Molenda ENUM_TO_CSTR(FunctionInitial); 340c980fa92SJason Molenda ENUM_TO_CSTR(FunctionChanged); 3416ab659a9SJason Molenda ENUM_TO_CSTR(FunctionIsOptimized); 342554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryFile); 343554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryLineNumber); 344554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryStartAddress); 345554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryEndAddress); 346554f68d3SGreg Clayton ENUM_TO_CSTR(CurrentPCArrow); 347554f68d3SGreg Clayton } 348554f68d3SGreg Clayton return "???"; 349554f68d3SGreg Clayton } 350554f68d3SGreg Clayton 351554f68d3SGreg Clayton #undef ENUM_TO_CSTR 352554f68d3SGreg Clayton 353b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const { 354554f68d3SGreg Clayton s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 355554f68d3SGreg Clayton if (fmt != eFormatDefault) 356554f68d3SGreg Clayton s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); 357554f68d3SGreg Clayton if (!string.empty()) 358554f68d3SGreg Clayton s.Printf("string = \"%s\"", string.c_str()); 359554f68d3SGreg Clayton if (!printf_format.empty()) 360554f68d3SGreg Clayton s.Printf("printf_format = \"%s\"", printf_format.c_str()); 361554f68d3SGreg Clayton if (number != 0) 362554f68d3SGreg Clayton s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 363554f68d3SGreg Clayton if (deref) 364554f68d3SGreg Clayton s.Printf("deref = true, "); 365554f68d3SGreg Clayton s.EOL(); 366b9c1b51eSKate Stone for (const auto &child : children) { 367554f68d3SGreg Clayton child.Dump(s, depth + 1); 368554f68d3SGreg Clayton } 369554f68d3SGreg Clayton } 370554f68d3SGreg Clayton 371554f68d3SGreg Clayton template <typename T> 372b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, 373b9c1b51eSKate Stone const ExecutionContext *exe_ctx, T t, 374b9c1b51eSKate Stone const char *script_function_name) { 375554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 376554f68d3SGreg Clayton 377b9c1b51eSKate Stone if (target) { 378b9c1b51eSKate Stone ScriptInterpreter *script_interpreter = 379b9c1b51eSKate Stone target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 380b9c1b51eSKate Stone if (script_interpreter) { 381554f68d3SGreg Clayton Error error; 382554f68d3SGreg Clayton std::string script_output; 383554f68d3SGreg Clayton 384b9c1b51eSKate Stone if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, 385b9c1b51eSKate Stone script_output, error) && 386b9c1b51eSKate Stone error.Success()) { 387554f68d3SGreg Clayton s.Printf("%s", script_output.c_str()); 388554f68d3SGreg Clayton return true; 389b9c1b51eSKate Stone } else { 390554f68d3SGreg Clayton s.Printf("<error: %s>", error.AsCString()); 391554f68d3SGreg Clayton } 392554f68d3SGreg Clayton } 393554f68d3SGreg Clayton } 394554f68d3SGreg Clayton return false; 395554f68d3SGreg Clayton } 396554f68d3SGreg Clayton 397b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc, 398b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address &addr, 399b9c1b51eSKate Stone bool print_file_addr_or_load_addr) { 400554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 401554f68d3SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 402554f68d3SGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 403554f68d3SGreg Clayton vaddr = addr.GetLoadAddress(target); 404554f68d3SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 405554f68d3SGreg Clayton vaddr = addr.GetFileAddress(); 406554f68d3SGreg Clayton 407b9c1b51eSKate Stone if (vaddr != LLDB_INVALID_ADDRESS) { 408554f68d3SGreg Clayton int addr_width = 0; 409b9c1b51eSKate Stone if (exe_ctx && target) { 410554f68d3SGreg Clayton addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 411554f68d3SGreg Clayton } 412554f68d3SGreg Clayton if (addr_width == 0) 413554f68d3SGreg Clayton addr_width = 16; 414b9c1b51eSKate Stone if (print_file_addr_or_load_addr) { 415a74f37a5SEugene Zelenko ExecutionContextScope *exe_scope = nullptr; 416554f68d3SGreg Clayton if (exe_ctx) 417554f68d3SGreg Clayton exe_scope = exe_ctx->GetBestExecutionContextScope(); 418b9c1b51eSKate Stone addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, 419b9c1b51eSKate Stone Address::DumpStyleModuleWithFileAddress, 0); 420b9c1b51eSKate Stone } else { 421554f68d3SGreg Clayton s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 422554f68d3SGreg Clayton } 423554f68d3SGreg Clayton return true; 424554f68d3SGreg Clayton } 425554f68d3SGreg Clayton return false; 426554f68d3SGreg Clayton } 427554f68d3SGreg Clayton 428b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, 429554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 430554f68d3SGreg Clayton const Address &format_addr, 431b9c1b51eSKate Stone bool concrete_only, bool no_padding, 432b9c1b51eSKate Stone bool print_zero_offsets) { 433b9c1b51eSKate Stone if (format_addr.IsValid()) { 434554f68d3SGreg Clayton Address func_addr; 435554f68d3SGreg Clayton 436b9c1b51eSKate Stone if (sc) { 437b9c1b51eSKate Stone if (sc->function) { 438554f68d3SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 439b9c1b51eSKate Stone if (sc->block && !concrete_only) { 440554f68d3SGreg Clayton // Check to make sure we aren't in an inline 441554f68d3SGreg Clayton // function. If we are, use the inline block 442554f68d3SGreg Clayton // range that contains "format_addr" since 443554f68d3SGreg Clayton // blocks can be discontiguous. 444554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 445554f68d3SGreg Clayton AddressRange inline_range; 446b9c1b51eSKate Stone if (inline_block && 447b9c1b51eSKate Stone inline_block->GetRangeContainingAddress(format_addr, 448b9c1b51eSKate Stone inline_range)) 449554f68d3SGreg Clayton func_addr = inline_range.GetBaseAddress(); 450554f68d3SGreg Clayton } 451b9c1b51eSKate Stone } else if (sc->symbol && sc->symbol->ValueIsAddress()) 452358cf1eaSGreg Clayton func_addr = sc->symbol->GetAddressRef(); 453554f68d3SGreg Clayton } 454554f68d3SGreg Clayton 455b9c1b51eSKate Stone if (func_addr.IsValid()) { 456554f68d3SGreg Clayton const char *addr_offset_padding = no_padding ? "" : " "; 457554f68d3SGreg Clayton 458b9c1b51eSKate Stone if (func_addr.GetSection() == format_addr.GetSection()) { 459554f68d3SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 460554f68d3SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 461b9c1b51eSKate Stone if (addr_file_addr > func_file_addr || 462b9c1b51eSKate Stone (addr_file_addr == func_file_addr && print_zero_offsets)) { 463b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 464b9c1b51eSKate Stone addr_file_addr - func_file_addr); 465b9c1b51eSKate Stone } else if (addr_file_addr < func_file_addr) { 466b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 467b9c1b51eSKate Stone func_file_addr - addr_file_addr); 468c980fa92SJason Molenda } 469554f68d3SGreg Clayton return true; 470b9c1b51eSKate Stone } else { 471554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 472b9c1b51eSKate Stone if (target) { 473554f68d3SGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress(target); 474554f68d3SGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress(target); 475b9c1b51eSKate Stone if (addr_load_addr > func_load_addr || 476b9c1b51eSKate Stone (addr_load_addr == func_load_addr && print_zero_offsets)) { 477b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 478b9c1b51eSKate Stone addr_load_addr - func_load_addr); 479b9c1b51eSKate Stone } else if (addr_load_addr < func_load_addr) { 480b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 481b9c1b51eSKate Stone func_load_addr - addr_load_addr); 482c980fa92SJason Molenda } 483554f68d3SGreg Clayton return true; 484554f68d3SGreg Clayton } 485554f68d3SGreg Clayton } 486554f68d3SGreg Clayton } 487554f68d3SGreg Clayton } 488554f68d3SGreg Clayton return false; 489554f68d3SGreg Clayton } 490554f68d3SGreg Clayton 491b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath, 492554f68d3SGreg Clayton size_t &close_bracket_index, 493554f68d3SGreg Clayton const char *&var_name_final_if_array_range, 494b9c1b51eSKate Stone int64_t &index_lower, int64_t &index_higher) { 4954edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 496554f68d3SGreg Clayton close_bracket_index = llvm::StringRef::npos; 497554f68d3SGreg Clayton const size_t open_bracket_index = subpath.find('['); 498b9c1b51eSKate Stone if (open_bracket_index == llvm::StringRef::npos) { 499554f68d3SGreg Clayton if (log) 500554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 501554f68d3SGreg Clayton return false; 502554f68d3SGreg Clayton } 503554f68d3SGreg Clayton 504554f68d3SGreg Clayton close_bracket_index = subpath.find(']', open_bracket_index + 1); 505554f68d3SGreg Clayton 506b9c1b51eSKate Stone if (close_bracket_index == llvm::StringRef::npos) { 507554f68d3SGreg Clayton if (log) 508554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 509554f68d3SGreg Clayton return false; 510b9c1b51eSKate Stone } else { 511554f68d3SGreg Clayton var_name_final_if_array_range = subpath.data() + open_bracket_index; 512554f68d3SGreg Clayton 513b9c1b51eSKate Stone if (close_bracket_index - open_bracket_index == 1) { 514554f68d3SGreg Clayton if (log) 515b9c1b51eSKate Stone log->Printf( 516b9c1b51eSKate Stone "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 517554f68d3SGreg Clayton index_lower = 0; 518b9c1b51eSKate Stone } else { 519554f68d3SGreg Clayton const size_t separator_index = subpath.find('-', open_bracket_index + 1); 520554f68d3SGreg Clayton 521b9c1b51eSKate Stone if (separator_index == llvm::StringRef::npos) { 522554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 523a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 524554f68d3SGreg Clayton index_higher = index_lower; 525554f68d3SGreg Clayton if (log) 526b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 527b9c1b51eSKate Stone "] detected, high index is same", 528b9c1b51eSKate Stone index_lower); 529b9c1b51eSKate Stone } else { 530554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 531554f68d3SGreg Clayton const char *index_higher_cstr = subpath.data() + separator_index + 1; 532a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 533a74f37a5SEugene Zelenko index_higher = ::strtoul(index_higher_cstr, nullptr, 0); 534554f68d3SGreg Clayton if (log) 535b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", 536b9c1b51eSKate Stone index_lower, index_higher); 537554f68d3SGreg Clayton } 538b9c1b51eSKate Stone if (index_lower > index_higher && index_higher > 0) { 539554f68d3SGreg Clayton if (log) 540554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] swapping indices"); 541554f68d3SGreg Clayton const int64_t temp = index_lower; 542554f68d3SGreg Clayton index_lower = index_higher; 543554f68d3SGreg Clayton index_higher = temp; 544554f68d3SGreg Clayton } 545554f68d3SGreg Clayton } 546554f68d3SGreg Clayton } 547554f68d3SGreg Clayton return true; 548554f68d3SGreg Clayton } 549554f68d3SGreg Clayton 550b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { 551b9c1b51eSKate Stone switch (file_kind) { 552554f68d3SGreg Clayton case FileKind::FileError: 553554f68d3SGreg Clayton break; 554554f68d3SGreg Clayton 555554f68d3SGreg Clayton case FileKind::Basename: 556b9c1b51eSKate Stone if (file.GetFilename()) { 557554f68d3SGreg Clayton s << file.GetFilename(); 558554f68d3SGreg Clayton return true; 559554f68d3SGreg Clayton } 560554f68d3SGreg Clayton break; 561554f68d3SGreg Clayton 562554f68d3SGreg Clayton case FileKind::Dirname: 563b9c1b51eSKate Stone if (file.GetDirectory()) { 564554f68d3SGreg Clayton s << file.GetDirectory(); 565554f68d3SGreg Clayton return true; 566554f68d3SGreg Clayton } 567554f68d3SGreg Clayton break; 568554f68d3SGreg Clayton 569554f68d3SGreg Clayton case FileKind::Fullpath: 570b9c1b51eSKate Stone if (file) { 571554f68d3SGreg Clayton s << file; 572554f68d3SGreg Clayton return true; 573554f68d3SGreg Clayton } 574554f68d3SGreg Clayton break; 575554f68d3SGreg Clayton } 576554f68d3SGreg Clayton return false; 577554f68d3SGreg Clayton } 578554f68d3SGreg Clayton 579b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, 580b9c1b51eSKate Stone uint32_t reg_num, Format format) 581554f68d3SGreg Clayton 582554f68d3SGreg Clayton { 583b9c1b51eSKate Stone if (frame) { 584554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 585554f68d3SGreg Clayton 586b9c1b51eSKate Stone if (reg_ctx) { 587b9c1b51eSKate Stone const uint32_t lldb_reg_num = 588b9c1b51eSKate Stone reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 589b9c1b51eSKate Stone if (lldb_reg_num != LLDB_INVALID_REGNUM) { 590b9c1b51eSKate Stone const RegisterInfo *reg_info = 591b9c1b51eSKate Stone reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); 592b9c1b51eSKate Stone if (reg_info) { 593554f68d3SGreg Clayton RegisterValue reg_value; 594b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 595554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 596554f68d3SGreg Clayton return true; 597554f68d3SGreg Clayton } 598554f68d3SGreg Clayton } 599554f68d3SGreg Clayton } 600554f68d3SGreg Clayton } 601554f68d3SGreg Clayton } 602554f68d3SGreg Clayton return false; 603554f68d3SGreg Clayton } 604554f68d3SGreg Clayton 605b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, 606554f68d3SGreg Clayton StackFrame *frame, 607b9c1b51eSKate Stone bool deref_pointer) { 6084edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 609554f68d3SGreg Clayton const char *ptr_deref_format = "[%d]"; 610554f68d3SGreg Clayton std::string ptr_deref_buffer(10, 0); 611554f68d3SGreg Clayton ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 612554f68d3SGreg Clayton if (log) 613b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] name to deref: %s", 614b9c1b51eSKate Stone ptr_deref_buffer.c_str()); 615554f68d3SGreg Clayton const char *first_unparsed; 616554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 617554f68d3SGreg Clayton ValueObject::ExpressionPathEndResultType final_value_type; 618554f68d3SGreg Clayton ValueObject::ExpressionPathScanEndReason reason_to_stop; 619b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 620b9c1b51eSKate Stone (deref_pointer ? ValueObject::eExpressionPathAftermathDereference 621b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 622b9c1b51eSKate Stone ValueObjectSP item = valobj->GetValueForExpressionPath( 623b9c1b51eSKate Stone ptr_deref_buffer.c_str(), &first_unparsed, &reason_to_stop, 624b9c1b51eSKate Stone &final_value_type, options, &what_next); 625b9c1b51eSKate Stone if (!item) { 626554f68d3SGreg Clayton if (log) 627b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why " 628b9c1b51eSKate Stone "stopping = %d," 629554f68d3SGreg Clayton " final_value_type %d", 630554f68d3SGreg Clayton first_unparsed, reason_to_stop, final_value_type); 631b9c1b51eSKate Stone } else { 632554f68d3SGreg Clayton if (log) 633b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, " 634b9c1b51eSKate Stone "why stopping = %d," 635554f68d3SGreg Clayton " final_value_type %d", 636554f68d3SGreg Clayton first_unparsed, reason_to_stop, final_value_type); 637554f68d3SGreg Clayton } 638554f68d3SGreg Clayton return item; 639554f68d3SGreg Clayton } 640554f68d3SGreg Clayton 641b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar( 642b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle style) { 643b9c1b51eSKate Stone switch (style) { 644b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: 645b9c1b51eSKate Stone return '@'; 646b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleValue: 647b9c1b51eSKate Stone return 'V'; 648b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLocation: 649b9c1b51eSKate Stone return 'L'; 650b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleSummary: 651b9c1b51eSKate Stone return 'S'; 652b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleChildrenCount: 653b9c1b51eSKate Stone return '#'; 654b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleType: 655b9c1b51eSKate Stone return 'T'; 656b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleName: 657b9c1b51eSKate Stone return 'N'; 658b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleExpressionPath: 659b9c1b51eSKate Stone return '>'; 660554f68d3SGreg Clayton } 661554f68d3SGreg Clayton return '\0'; 662554f68d3SGreg Clayton } 663554f68d3SGreg Clayton 664b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc, 665554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 666b9c1b51eSKate Stone const FormatEntity::Entry &entry, ValueObject *valobj) { 667a74f37a5SEugene Zelenko if (valobj == nullptr) 668554f68d3SGreg Clayton return false; 669554f68d3SGreg Clayton 6704edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 671554f68d3SGreg Clayton Format custom_format = eFormatInvalid; 672b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle val_obj_display = 673b9c1b51eSKate Stone entry.string.empty() 674b9c1b51eSKate Stone ? ValueObject::eValueObjectRepresentationStyleValue 675b9c1b51eSKate Stone : ValueObject::eValueObjectRepresentationStyleSummary; 676554f68d3SGreg Clayton 677554f68d3SGreg Clayton bool do_deref_pointer = entry.deref; 678554f68d3SGreg Clayton bool is_script = false; 679b9c1b51eSKate Stone switch (entry.type) { 680554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariable: 681554f68d3SGreg Clayton is_script = true; 682554f68d3SGreg Clayton break; 683554f68d3SGreg Clayton 684554f68d3SGreg Clayton case FormatEntity::Entry::Type::Variable: 685554f68d3SGreg Clayton custom_format = entry.fmt; 686554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 687554f68d3SGreg Clayton break; 688554f68d3SGreg Clayton 689554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariableSynthetic: 690554f68d3SGreg Clayton is_script = true; 69162e0681aSJason Molenda LLVM_FALLTHROUGH; 692554f68d3SGreg Clayton case FormatEntity::Entry::Type::VariableSynthetic: 693554f68d3SGreg Clayton custom_format = entry.fmt; 694554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 695b9c1b51eSKate Stone if (!valobj->IsSynthetic()) { 696554f68d3SGreg Clayton valobj = valobj->GetSyntheticValue().get(); 697554f68d3SGreg Clayton if (valobj == nullptr) 698554f68d3SGreg Clayton return false; 699554f68d3SGreg Clayton } 700554f68d3SGreg Clayton break; 701554f68d3SGreg Clayton 702554f68d3SGreg Clayton default: 703554f68d3SGreg Clayton return false; 704554f68d3SGreg Clayton } 705554f68d3SGreg Clayton 706a74f37a5SEugene Zelenko if (valobj == nullptr) 707554f68d3SGreg Clayton return false; 708554f68d3SGreg Clayton 709b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 710b9c1b51eSKate Stone (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference 711b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 712554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 713b9c1b51eSKate Stone options.DontCheckDotVsArrowSyntax() 714b9c1b51eSKate Stone .DoAllowBitfieldSyntax() 715b9c1b51eSKate Stone .DoAllowFragileIVar() 716b9c1b51eSKate Stone .SetSyntheticChildrenTraversal( 717b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions:: 718b9c1b51eSKate Stone SyntheticChildrenTraversal::Both); 719a74f37a5SEugene Zelenko ValueObject *target = nullptr; 720a74f37a5SEugene Zelenko const char *var_name_final_if_array_range = nullptr; 721554f68d3SGreg Clayton size_t close_bracket_index = llvm::StringRef::npos; 722554f68d3SGreg Clayton int64_t index_lower = -1; 723554f68d3SGreg Clayton int64_t index_higher = -1; 724554f68d3SGreg Clayton bool is_array_range = false; 725554f68d3SGreg Clayton const char *first_unparsed; 726554f68d3SGreg Clayton bool was_plain_var = false; 727554f68d3SGreg Clayton bool was_var_format = false; 728554f68d3SGreg Clayton bool was_var_indexed = false; 729b9c1b51eSKate Stone ValueObject::ExpressionPathScanEndReason reason_to_stop = 730b9c1b51eSKate Stone ValueObject::eExpressionPathScanEndReasonEndOfString; 731b9c1b51eSKate Stone ValueObject::ExpressionPathEndResultType final_value_type = 732b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypePlain; 733554f68d3SGreg Clayton 734b9c1b51eSKate Stone if (is_script) { 735554f68d3SGreg Clayton return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); 736554f68d3SGreg Clayton } 737554f68d3SGreg Clayton 738554f68d3SGreg Clayton llvm::StringRef subpath(entry.string); 739554f68d3SGreg Clayton // simplest case ${var}, just print valobj's value 740b9c1b51eSKate Stone if (entry.string.empty()) { 741b9c1b51eSKate Stone if (entry.printf_format.empty() && entry.fmt == eFormatDefault && 742b9c1b51eSKate Stone entry.number == ValueObject::eValueObjectRepresentationStyleValue) 743554f68d3SGreg Clayton was_plain_var = true; 744554f68d3SGreg Clayton else 745554f68d3SGreg Clayton was_var_format = true; 746554f68d3SGreg Clayton target = valobj; 747b9c1b51eSKate Stone } else // this is ${var.something} or multiple .something nested 748554f68d3SGreg Clayton { 749554f68d3SGreg Clayton if (entry.string[0] == '[') 750554f68d3SGreg Clayton was_var_indexed = true; 751b9c1b51eSKate Stone ScanBracketedRange(subpath, close_bracket_index, 752b9c1b51eSKate Stone var_name_final_if_array_range, index_lower, 753554f68d3SGreg Clayton index_higher); 754554f68d3SGreg Clayton 755554f68d3SGreg Clayton Error error; 756554f68d3SGreg Clayton 757554f68d3SGreg Clayton const std::string &expr_path = entry.string; 758554f68d3SGreg Clayton 759554f68d3SGreg Clayton if (log) 760b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", 761b9c1b51eSKate Stone expr_path.c_str()); 762554f68d3SGreg Clayton 763b9c1b51eSKate Stone target = valobj 764b9c1b51eSKate Stone ->GetValueForExpressionPath(expr_path.c_str(), &first_unparsed, 765b9c1b51eSKate Stone &reason_to_stop, &final_value_type, 766b9c1b51eSKate Stone options, &what_next) 767b9c1b51eSKate Stone .get(); 768554f68d3SGreg Clayton 769b9c1b51eSKate Stone if (!target) { 770554f68d3SGreg Clayton if (log) 771b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, " 772b9c1b51eSKate Stone "why stopping = %d," 773554f68d3SGreg Clayton " final_value_type %d", 774554f68d3SGreg Clayton first_unparsed, reason_to_stop, final_value_type); 775554f68d3SGreg Clayton return false; 776b9c1b51eSKate Stone } else { 777554f68d3SGreg Clayton if (log) 778b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = " 779b9c1b51eSKate Stone "%s, why stopping = %d," 780554f68d3SGreg Clayton " final_value_type %d", 781554f68d3SGreg Clayton first_unparsed, reason_to_stop, final_value_type); 782b9c1b51eSKate Stone target = target 783b9c1b51eSKate Stone ->GetQualifiedRepresentationIfAvailable( 784b9c1b51eSKate Stone target->GetDynamicValueType(), true) 785b9c1b51eSKate Stone .get(); 786554f68d3SGreg Clayton } 787554f68d3SGreg Clayton } 788554f68d3SGreg Clayton 789b9c1b51eSKate Stone is_array_range = 790b9c1b51eSKate Stone (final_value_type == 791b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeBoundedRange || 792b9c1b51eSKate Stone final_value_type == 793b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeUnboundedRange); 794554f68d3SGreg Clayton 795b9c1b51eSKate Stone do_deref_pointer = 796b9c1b51eSKate Stone (what_next == ValueObject::eExpressionPathAftermathDereference); 797554f68d3SGreg Clayton 798b9c1b51eSKate Stone if (do_deref_pointer && !is_array_range) { 799554f68d3SGreg Clayton // I have not deref-ed yet, let's do it 800b9c1b51eSKate Stone // this happens when we are not going through 801b9c1b51eSKate Stone // GetValueForVariableExpressionPath 802554f68d3SGreg Clayton // to get to the target ValueObject 803554f68d3SGreg Clayton Error error; 804554f68d3SGreg Clayton target = target->Dereference(error).get(); 805b9c1b51eSKate Stone if (error.Fail()) { 806554f68d3SGreg Clayton if (log) 807b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", 808b9c1b51eSKate Stone error.AsCString("unknown")); 809554f68d3SGreg Clayton return false; 810554f68d3SGreg Clayton } 811554f68d3SGreg Clayton do_deref_pointer = false; 812554f68d3SGreg Clayton } 813554f68d3SGreg Clayton 814b9c1b51eSKate Stone if (!target) { 815554f68d3SGreg Clayton if (log) 816b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] could not calculate target for " 817b9c1b51eSKate Stone "prompt expression"); 818554f68d3SGreg Clayton return false; 819554f68d3SGreg Clayton } 820554f68d3SGreg Clayton 821554f68d3SGreg Clayton // we do not want to use the summary for a bitfield of type T:n 822554f68d3SGreg Clayton // if we were originally dealing with just a T - that would get 823554f68d3SGreg Clayton // us into an endless recursion 824b9c1b51eSKate Stone if (target->IsBitfield() && was_var_indexed) { 825554f68d3SGreg Clayton // TODO: check for a (T:n)-specific summary - we should still obey that 826554f68d3SGreg Clayton StreamString bitfield_name; 827b9c1b51eSKate Stone bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), 828b9c1b51eSKate Stone target->GetBitfieldBitSize()); 829b9c1b51eSKate Stone lldb::TypeNameSpecifierImplSP type_sp( 830b9c1b51eSKate Stone new TypeNameSpecifierImpl(bitfield_name.GetData(), false)); 831b9c1b51eSKate Stone if (val_obj_display == 832b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary && 833b9c1b51eSKate Stone !DataVisualization::GetSummaryForType(type_sp)) 834554f68d3SGreg Clayton val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 835554f68d3SGreg Clayton } 836554f68d3SGreg Clayton 837554f68d3SGreg Clayton // TODO use flags for these 838b9c1b51eSKate Stone const uint32_t type_info_flags = 839b9c1b51eSKate Stone target->GetCompilerType().GetTypeInfo(nullptr); 840554f68d3SGreg Clayton bool is_array = (type_info_flags & eTypeIsArray) != 0; 841554f68d3SGreg Clayton bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 84299558cc4SGreg Clayton bool is_aggregate = target->GetCompilerType().IsAggregateType(); 843554f68d3SGreg Clayton 844b9c1b51eSKate Stone if ((is_array || is_pointer) && (!is_array_range) && 845b9c1b51eSKate Stone val_obj_display == 846b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue) // this should be 847b9c1b51eSKate Stone // wrong, but there 848b9c1b51eSKate Stone // are some 849b9c1b51eSKate Stone // exceptions 850554f68d3SGreg Clayton { 851554f68d3SGreg Clayton StreamString str_temp; 852554f68d3SGreg Clayton if (log) 853b9c1b51eSKate Stone log->Printf( 854b9c1b51eSKate Stone "[Debugger::FormatPrompt] I am into array || pointer && !range"); 855554f68d3SGreg Clayton 856b9c1b51eSKate Stone if (target->HasSpecialPrintableRepresentation(val_obj_display, 857b9c1b51eSKate Stone custom_format)) { 858554f68d3SGreg Clayton // try to use the special cases 859b9c1b51eSKate Stone bool success = target->DumpPrintableRepresentation( 860b9c1b51eSKate Stone str_temp, val_obj_display, custom_format); 861554f68d3SGreg Clayton if (log) 862b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] special cases did%s match", 863b9c1b51eSKate Stone success ? "" : "n't"); 864554f68d3SGreg Clayton 865554f68d3SGreg Clayton // should not happen 866554f68d3SGreg Clayton if (success) 867554f68d3SGreg Clayton s << str_temp.GetData(); 868554f68d3SGreg Clayton return true; 869b9c1b51eSKate Stone } else { 870554f68d3SGreg Clayton if (was_plain_var) // if ${var} 871554f68d3SGreg Clayton { 872554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 873b9c1b51eSKate Stone } else if (is_pointer) // if pointer, value is the address stored 874554f68d3SGreg Clayton { 875b9c1b51eSKate Stone target->DumpPrintableRepresentation( 876b9c1b51eSKate Stone s, val_obj_display, custom_format, 877*65d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable); 878554f68d3SGreg Clayton } 879554f68d3SGreg Clayton return true; 880554f68d3SGreg Clayton } 881554f68d3SGreg Clayton } 882554f68d3SGreg Clayton 883b9c1b51eSKate Stone // if directly trying to print ${var}, and this is an aggregate, display a 884b9c1b51eSKate Stone // nice 885554f68d3SGreg Clayton // type @ location message 886b9c1b51eSKate Stone if (is_aggregate && was_plain_var) { 887554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 888554f68d3SGreg Clayton return true; 889554f68d3SGreg Clayton } 890554f68d3SGreg Clayton 891b9c1b51eSKate Stone // if directly trying to print ${var%V}, and this is an aggregate, do not let 892b9c1b51eSKate Stone // the user do it 893b9c1b51eSKate Stone if (is_aggregate && 894b9c1b51eSKate Stone ((was_var_format && 895b9c1b51eSKate Stone val_obj_display == 896b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue))) { 897554f68d3SGreg Clayton s << "<invalid use of aggregate type>"; 898554f68d3SGreg Clayton return true; 899554f68d3SGreg Clayton } 900554f68d3SGreg Clayton 901b9c1b51eSKate Stone if (!is_array_range) { 902554f68d3SGreg Clayton if (log) 903554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 904b9c1b51eSKate Stone return target->DumpPrintableRepresentation(s, val_obj_display, 905b9c1b51eSKate Stone custom_format); 906b9c1b51eSKate Stone } else { 907554f68d3SGreg Clayton if (log) 908554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 909554f68d3SGreg Clayton if (!is_array && !is_pointer) 910554f68d3SGreg Clayton return false; 911554f68d3SGreg Clayton if (log) 912554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] handle as array"); 913e8376261SVince Harron StreamString special_directions_stream; 914554f68d3SGreg Clayton llvm::StringRef special_directions; 915b9c1b51eSKate Stone if (close_bracket_index != llvm::StringRef::npos && 916b9c1b51eSKate Stone subpath.size() > close_bracket_index) { 917554f68d3SGreg Clayton ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); 918b9c1b51eSKate Stone special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", 919554f68d3SGreg Clayton additional_data.GetCString()); 920554f68d3SGreg Clayton 921b9c1b51eSKate Stone if (entry.fmt != eFormatDefault) { 922b9c1b51eSKate Stone const char format_char = 923b9c1b51eSKate Stone FormatManager::GetFormatAsFormatChar(entry.fmt); 924554f68d3SGreg Clayton if (format_char != '\0') 925554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", format_char); 926b9c1b51eSKate Stone else { 927b9c1b51eSKate Stone const char *format_cstr = 928b9c1b51eSKate Stone FormatManager::GetFormatAsCString(entry.fmt); 929554f68d3SGreg Clayton special_directions_stream.Printf("%%%s", format_cstr); 930554f68d3SGreg Clayton } 931b9c1b51eSKate Stone } else if (entry.number != 0) { 932b9c1b51eSKate Stone const char style_char = ConvertValueObjectStyleToChar( 933b9c1b51eSKate Stone (ValueObject::ValueObjectRepresentationStyle)entry.number); 934554f68d3SGreg Clayton if (style_char) 935554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", style_char); 936554f68d3SGreg Clayton } 937554f68d3SGreg Clayton special_directions_stream.PutChar('}'); 938b9c1b51eSKate Stone special_directions = 939b9c1b51eSKate Stone llvm::StringRef(special_directions_stream.GetString()); 940554f68d3SGreg Clayton } 941554f68d3SGreg Clayton 942554f68d3SGreg Clayton // let us display items index_lower thru index_higher of this array 943554f68d3SGreg Clayton s.PutChar('['); 944554f68d3SGreg Clayton 945554f68d3SGreg Clayton if (index_higher < 0) 946554f68d3SGreg Clayton index_higher = valobj->GetNumChildren() - 1; 947554f68d3SGreg Clayton 948b9c1b51eSKate Stone uint32_t max_num_children = 949b9c1b51eSKate Stone target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 950554f68d3SGreg Clayton 951554f68d3SGreg Clayton bool success = true; 952b9c1b51eSKate Stone for (int64_t index = index_lower; index <= index_higher; ++index) { 953b9c1b51eSKate Stone ValueObject *item = 954b9c1b51eSKate Stone ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) 955b9c1b51eSKate Stone .get(); 956554f68d3SGreg Clayton 957b9c1b51eSKate Stone if (!item) { 958554f68d3SGreg Clayton if (log) 959b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " 960b9c1b51eSKate Stone "index %" PRId64, 961b9c1b51eSKate Stone index); 962b9c1b51eSKate Stone } else { 963554f68d3SGreg Clayton if (log) 964b9c1b51eSKate Stone log->Printf( 965b9c1b51eSKate Stone "[Debugger::FormatPrompt] special_directions for child item: %s", 966b9c1b51eSKate Stone special_directions.data() ? special_directions.data() : ""); 967554f68d3SGreg Clayton } 968554f68d3SGreg Clayton 969b9c1b51eSKate Stone if (special_directions.empty()) { 970b9c1b51eSKate Stone success &= item->DumpPrintableRepresentation(s, val_obj_display, 971b9c1b51eSKate Stone custom_format); 972b9c1b51eSKate Stone } else { 973b9c1b51eSKate Stone success &= FormatEntity::FormatStringRef( 974b9c1b51eSKate Stone special_directions, s, sc, exe_ctx, nullptr, item, false, false); 975554f68d3SGreg Clayton } 976554f68d3SGreg Clayton 977b9c1b51eSKate Stone if (--max_num_children == 0) { 978554f68d3SGreg Clayton s.PutCString(", ..."); 979554f68d3SGreg Clayton break; 980554f68d3SGreg Clayton } 981554f68d3SGreg Clayton 982554f68d3SGreg Clayton if (index < index_higher) 983554f68d3SGreg Clayton s.PutChar(','); 984554f68d3SGreg Clayton } 985554f68d3SGreg Clayton s.PutChar(']'); 986554f68d3SGreg Clayton return success; 987554f68d3SGreg Clayton } 988554f68d3SGreg Clayton } 989554f68d3SGreg Clayton 990b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, 991b9c1b51eSKate Stone Format format) { 992b9c1b51eSKate Stone if (frame) { 993554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 994554f68d3SGreg Clayton 995b9c1b51eSKate Stone if (reg_ctx) { 996554f68d3SGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 997b9c1b51eSKate Stone if (reg_info) { 998554f68d3SGreg Clayton RegisterValue reg_value; 999b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 1000554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 1001554f68d3SGreg Clayton return true; 1002554f68d3SGreg Clayton } 1003554f68d3SGreg Clayton } 1004554f68d3SGreg Clayton } 1005554f68d3SGreg Clayton } 1006554f68d3SGreg Clayton return false; 1007554f68d3SGreg Clayton } 1008554f68d3SGreg Clayton 1009b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse( 1010b9c1b51eSKate Stone const FormatEntity::Entry &entry, 1011554f68d3SGreg Clayton const StructuredData::ObjectSP &thread_info_dictionary, 1012b9c1b51eSKate Stone const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { 1013554f68d3SGreg Clayton llvm::StringRef path(entry.string); 1014554f68d3SGreg Clayton 1015b9c1b51eSKate Stone StructuredData::ObjectSP value = 1016b9c1b51eSKate Stone thread_info_dictionary->GetObjectForDotSeparatedPath(path); 1017554f68d3SGreg Clayton 1018b9c1b51eSKate Stone if (value) { 1019b9c1b51eSKate Stone if (value->GetType() == StructuredData::Type::eTypeInteger) { 1020554f68d3SGreg Clayton const char *token_format = "0x%4.4" PRIx64; 1021554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1022554f68d3SGreg Clayton token_format = entry.printf_format.c_str(); 1023554f68d3SGreg Clayton s.Printf(token_format, value->GetAsInteger()->GetValue()); 1024554f68d3SGreg Clayton return true; 1025b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeFloat) { 1026554f68d3SGreg Clayton s.Printf("%f", value->GetAsFloat()->GetValue()); 1027554f68d3SGreg Clayton return true; 1028b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeString) { 1029554f68d3SGreg Clayton s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1030554f68d3SGreg Clayton return true; 1031b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeArray) { 1032b9c1b51eSKate Stone if (value->GetAsArray()->GetSize() > 0) { 1033554f68d3SGreg Clayton s.Printf("%zu", value->GetAsArray()->GetSize()); 1034554f68d3SGreg Clayton return true; 1035554f68d3SGreg Clayton } 1036b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeDictionary) { 1037b9c1b51eSKate Stone s.Printf("%zu", 1038b9c1b51eSKate Stone value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1039554f68d3SGreg Clayton return true; 1040554f68d3SGreg Clayton } 1041554f68d3SGreg Clayton } 1042554f68d3SGreg Clayton 1043554f68d3SGreg Clayton return false; 1044554f68d3SGreg Clayton } 1045554f68d3SGreg Clayton 1046b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) { 1047554f68d3SGreg Clayton return (::strncmp(var_name_begin, var, strlen(var)) == 0); 1048554f68d3SGreg Clayton } 1049554f68d3SGreg Clayton 1050b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, 1051554f68d3SGreg Clayton const SymbolContext *sc, 1052554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1053b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1054554f68d3SGreg Clayton bool function_changed, 1055b9c1b51eSKate Stone bool initial_function) { 1056b9c1b51eSKate Stone if (!format_str.empty()) { 1057554f68d3SGreg Clayton FormatEntity::Entry root; 1058554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1059b9c1b51eSKate Stone if (error.Success()) { 1060b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1061b9c1b51eSKate Stone function_changed, initial_function); 1062554f68d3SGreg Clayton } 1063554f68d3SGreg Clayton } 1064554f68d3SGreg Clayton return false; 1065554f68d3SGreg Clayton } 1066a74f37a5SEugene Zelenko 1067b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s, 1068554f68d3SGreg Clayton const SymbolContext *sc, 1069554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1070b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1071b9c1b51eSKate Stone bool function_changed, bool initial_function) { 1072b9c1b51eSKate Stone if (format && format[0]) { 1073554f68d3SGreg Clayton FormatEntity::Entry root; 1074554f68d3SGreg Clayton llvm::StringRef format_str(format); 1075554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1076b9c1b51eSKate Stone if (error.Success()) { 1077b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1078b9c1b51eSKate Stone function_changed, initial_function); 1079554f68d3SGreg Clayton } 1080554f68d3SGreg Clayton } 1081554f68d3SGreg Clayton return false; 1082554f68d3SGreg Clayton } 1083554f68d3SGreg Clayton 1084b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s, 1085554f68d3SGreg Clayton const SymbolContext *sc, 1086b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address *addr, 1087b9c1b51eSKate Stone ValueObject *valobj, bool function_changed, 1088b9c1b51eSKate Stone bool initial_function) { 1089b9c1b51eSKate Stone switch (entry.type) { 1090554f68d3SGreg Clayton case Entry::Type::Invalid: 1091b9c1b51eSKate Stone case Entry::Type::ParentNumber: // Only used for 1092b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1093b9c1b51eSKate Stone case Entry::Type::ParentString: // Only used for 1094b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1095b9c1b51eSKate Stone case Entry::Type::InsertString: // Only used for 1096b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1097554f68d3SGreg Clayton return false; 1098554f68d3SGreg Clayton 1099554f68d3SGreg Clayton case Entry::Type::Root: 1100b9c1b51eSKate Stone for (const auto &child : entry.children) { 1101b9c1b51eSKate Stone if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, 1102b9c1b51eSKate Stone initial_function)) { 1103554f68d3SGreg Clayton return false; // If any item of root fails, then the formatting fails 1104554f68d3SGreg Clayton } 1105554f68d3SGreg Clayton } 1106554f68d3SGreg Clayton return true; // Only return true if all items succeeded 1107554f68d3SGreg Clayton 1108554f68d3SGreg Clayton case Entry::Type::String: 1109771ef6d4SMalcolm Parsons s.PutCString(entry.string); 1110554f68d3SGreg Clayton return true; 1111554f68d3SGreg Clayton 1112b9c1b51eSKate Stone case Entry::Type::Scope: { 1113554f68d3SGreg Clayton StreamString scope_stream; 1114554f68d3SGreg Clayton bool success = false; 1115b9c1b51eSKate Stone for (const auto &child : entry.children) { 1116b9c1b51eSKate Stone success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, 1117b9c1b51eSKate Stone function_changed, initial_function); 1118554f68d3SGreg Clayton if (!success) 1119554f68d3SGreg Clayton break; 1120554f68d3SGreg Clayton } 1121554f68d3SGreg Clayton // Only if all items in a scope succeed, then do we 1122554f68d3SGreg Clayton // print the output into the main stream 1123554f68d3SGreg Clayton if (success) 1124554f68d3SGreg Clayton s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1125554f68d3SGreg Clayton } 1126554f68d3SGreg Clayton return true; // Scopes always successfully print themselves 1127554f68d3SGreg Clayton 1128554f68d3SGreg Clayton case Entry::Type::Variable: 1129554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 1130554f68d3SGreg Clayton case Entry::Type::ScriptVariable: 1131554f68d3SGreg Clayton case Entry::Type::ScriptVariableSynthetic: 1132a74f37a5SEugene Zelenko return DumpValue(s, sc, exe_ctx, entry, valobj); 1133554f68d3SGreg Clayton 1134554f68d3SGreg Clayton case Entry::Type::AddressFile: 1135554f68d3SGreg Clayton case Entry::Type::AddressLoad: 1136554f68d3SGreg Clayton case Entry::Type::AddressLoadOrFile: 1137a74f37a5SEugene Zelenko return (addr != nullptr && addr->IsValid() && 1138b9c1b51eSKate Stone DumpAddress(s, sc, exe_ctx, *addr, 1139b9c1b51eSKate Stone entry.type == Entry::Type::AddressLoadOrFile)); 1140554f68d3SGreg Clayton 1141554f68d3SGreg Clayton case Entry::Type::ProcessID: 1142b9c1b51eSKate Stone if (exe_ctx) { 1143554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1144b9c1b51eSKate Stone if (process) { 1145554f68d3SGreg Clayton const char *format = "%" PRIu64; 1146554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1147554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1148554f68d3SGreg Clayton s.Printf(format, process->GetID()); 1149554f68d3SGreg Clayton return true; 1150554f68d3SGreg Clayton } 1151554f68d3SGreg Clayton } 1152554f68d3SGreg Clayton return false; 1153554f68d3SGreg Clayton 1154554f68d3SGreg Clayton case Entry::Type::ProcessFile: 1155b9c1b51eSKate Stone if (exe_ctx) { 1156554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1157b9c1b51eSKate Stone if (process) { 1158554f68d3SGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1159b9c1b51eSKate Stone if (exe_module) { 1160554f68d3SGreg Clayton if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1161554f68d3SGreg Clayton return true; 1162554f68d3SGreg Clayton } 1163554f68d3SGreg Clayton } 1164554f68d3SGreg Clayton } 1165554f68d3SGreg Clayton return false; 1166554f68d3SGreg Clayton 1167554f68d3SGreg Clayton case Entry::Type::ScriptProcess: 1168b9c1b51eSKate Stone if (exe_ctx) { 1169554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1170554f68d3SGreg Clayton if (process) 1171b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, process, 1172b9c1b51eSKate Stone entry.string.c_str()); 1173554f68d3SGreg Clayton } 1174554f68d3SGreg Clayton return false; 1175554f68d3SGreg Clayton 1176554f68d3SGreg Clayton case Entry::Type::ThreadID: 1177b9c1b51eSKate Stone if (exe_ctx) { 1178554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1179b9c1b51eSKate Stone if (thread) { 1180554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1181b9c1b51eSKate Stone if (!entry.printf_format.empty()) { 1182554f68d3SGreg Clayton // Watch for the special "tid" format... 1183b9c1b51eSKate Stone if (entry.printf_format == "tid") { 1184b9c1b51eSKate Stone // TODO(zturner): Rather than hardcoding this to be platform 1185b9c1b51eSKate Stone // specific, it should be controlled by a 1186b9c1b51eSKate Stone // setting and the default value of the setting can be different 1187b9c1b51eSKate Stone // depending on the platform. 1188554f68d3SGreg Clayton Target &target = thread->GetProcess()->GetTarget(); 1189554f68d3SGreg Clayton ArchSpec arch(target.GetArchitecture()); 1190b9c1b51eSKate Stone llvm::Triple::OSType ostype = arch.IsValid() 1191b9c1b51eSKate Stone ? arch.GetTriple().getOS() 1192b9c1b51eSKate Stone : llvm::Triple::UnknownOS; 1193b9c1b51eSKate Stone if ((ostype == llvm::Triple::FreeBSD) || 1194b9c1b51eSKate Stone (ostype == llvm::Triple::Linux)) { 1195554f68d3SGreg Clayton format = "%" PRIu64; 1196554f68d3SGreg Clayton } 1197b9c1b51eSKate Stone } else { 1198554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1199554f68d3SGreg Clayton } 1200554f68d3SGreg Clayton } 1201554f68d3SGreg Clayton s.Printf(format, thread->GetID()); 1202554f68d3SGreg Clayton return true; 1203554f68d3SGreg Clayton } 1204554f68d3SGreg Clayton } 1205554f68d3SGreg Clayton return false; 1206554f68d3SGreg Clayton 1207554f68d3SGreg Clayton case Entry::Type::ThreadProtocolID: 1208b9c1b51eSKate Stone if (exe_ctx) { 1209554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1210b9c1b51eSKate Stone if (thread) { 1211554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1212554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1213554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1214554f68d3SGreg Clayton s.Printf(format, thread->GetProtocolID()); 1215554f68d3SGreg Clayton return true; 1216554f68d3SGreg Clayton } 1217554f68d3SGreg Clayton } 1218554f68d3SGreg Clayton return false; 1219554f68d3SGreg Clayton 1220554f68d3SGreg Clayton case Entry::Type::ThreadIndexID: 1221b9c1b51eSKate Stone if (exe_ctx) { 1222554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1223b9c1b51eSKate Stone if (thread) { 1224554f68d3SGreg Clayton const char *format = "%" PRIu32; 1225554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1226554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1227554f68d3SGreg Clayton s.Printf(format, thread->GetIndexID()); 1228554f68d3SGreg Clayton return true; 1229554f68d3SGreg Clayton } 1230554f68d3SGreg Clayton } 1231554f68d3SGreg Clayton return false; 1232554f68d3SGreg Clayton 1233554f68d3SGreg Clayton case Entry::Type::ThreadName: 1234b9c1b51eSKate Stone if (exe_ctx) { 1235554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1236b9c1b51eSKate Stone if (thread) { 1237554f68d3SGreg Clayton const char *cstr = thread->GetName(); 1238b9c1b51eSKate Stone if (cstr && cstr[0]) { 1239554f68d3SGreg Clayton s.PutCString(cstr); 1240554f68d3SGreg Clayton return true; 1241554f68d3SGreg Clayton } 1242554f68d3SGreg Clayton } 1243554f68d3SGreg Clayton } 1244554f68d3SGreg Clayton return false; 1245554f68d3SGreg Clayton 1246554f68d3SGreg Clayton case Entry::Type::ThreadQueue: 1247b9c1b51eSKate Stone if (exe_ctx) { 1248554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1249b9c1b51eSKate Stone if (thread) { 1250554f68d3SGreg Clayton const char *cstr = thread->GetQueueName(); 1251b9c1b51eSKate Stone if (cstr && cstr[0]) { 1252554f68d3SGreg Clayton s.PutCString(cstr); 1253554f68d3SGreg Clayton return true; 1254554f68d3SGreg Clayton } 1255554f68d3SGreg Clayton } 1256554f68d3SGreg Clayton } 1257554f68d3SGreg Clayton return false; 1258554f68d3SGreg Clayton 1259554f68d3SGreg Clayton case Entry::Type::ThreadStopReason: 1260b9c1b51eSKate Stone if (exe_ctx) { 1261554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1262b9c1b51eSKate Stone if (thread) { 1263554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1264b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1265554f68d3SGreg Clayton const char *cstr = stop_info_sp->GetDescription(); 1266b9c1b51eSKate Stone if (cstr && cstr[0]) { 1267554f68d3SGreg Clayton s.PutCString(cstr); 1268554f68d3SGreg Clayton return true; 1269554f68d3SGreg Clayton } 1270554f68d3SGreg Clayton } 1271554f68d3SGreg Clayton } 1272554f68d3SGreg Clayton } 1273554f68d3SGreg Clayton return false; 1274554f68d3SGreg Clayton 1275554f68d3SGreg Clayton case Entry::Type::ThreadReturnValue: 1276b9c1b51eSKate Stone if (exe_ctx) { 1277554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1278b9c1b51eSKate Stone if (thread) { 1279554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1280b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1281b9c1b51eSKate Stone ValueObjectSP return_valobj_sp = 1282b9c1b51eSKate Stone StopInfo::GetReturnValueObject(stop_info_sp); 1283b9c1b51eSKate Stone if (return_valobj_sp) { 1284554f68d3SGreg Clayton return_valobj_sp->Dump(s); 1285554f68d3SGreg Clayton return true; 1286554f68d3SGreg Clayton } 1287554f68d3SGreg Clayton } 1288554f68d3SGreg Clayton } 1289554f68d3SGreg Clayton } 1290554f68d3SGreg Clayton return false; 1291554f68d3SGreg Clayton 1292554f68d3SGreg Clayton case Entry::Type::ThreadCompletedExpression: 1293b9c1b51eSKate Stone if (exe_ctx) { 1294554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1295b9c1b51eSKate Stone if (thread) { 1296554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1297b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1298b9c1b51eSKate Stone ExpressionVariableSP expression_var_sp = 1299b9c1b51eSKate Stone StopInfo::GetExpressionVariable(stop_info_sp); 1300b9c1b51eSKate Stone if (expression_var_sp && expression_var_sp->GetValueObject()) { 1301554f68d3SGreg Clayton expression_var_sp->GetValueObject()->Dump(s); 1302554f68d3SGreg Clayton return true; 1303554f68d3SGreg Clayton } 1304554f68d3SGreg Clayton } 1305554f68d3SGreg Clayton } 1306554f68d3SGreg Clayton } 1307554f68d3SGreg Clayton return false; 1308554f68d3SGreg Clayton 1309554f68d3SGreg Clayton case Entry::Type::ScriptThread: 1310b9c1b51eSKate Stone if (exe_ctx) { 1311554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1312554f68d3SGreg Clayton if (thread) 1313b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, thread, 1314b9c1b51eSKate Stone entry.string.c_str()); 1315554f68d3SGreg Clayton } 1316554f68d3SGreg Clayton return false; 1317554f68d3SGreg Clayton 1318554f68d3SGreg Clayton case Entry::Type::ThreadInfo: 1319b9c1b51eSKate Stone if (exe_ctx) { 1320554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1321b9c1b51eSKate Stone if (thread) { 1322554f68d3SGreg Clayton StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1323b9c1b51eSKate Stone if (object_sp && 1324b9c1b51eSKate Stone object_sp->GetType() == StructuredData::Type::eTypeDictionary) { 1325554f68d3SGreg Clayton if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) 1326554f68d3SGreg Clayton return true; 1327554f68d3SGreg Clayton } 1328554f68d3SGreg Clayton } 1329554f68d3SGreg Clayton } 1330554f68d3SGreg Clayton return false; 1331554f68d3SGreg Clayton 1332554f68d3SGreg Clayton case Entry::Type::TargetArch: 1333b9c1b51eSKate Stone if (exe_ctx) { 1334554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1335b9c1b51eSKate Stone if (target) { 1336554f68d3SGreg Clayton const ArchSpec &arch = target->GetArchitecture(); 1337b9c1b51eSKate Stone if (arch.IsValid()) { 1338554f68d3SGreg Clayton s.PutCString(arch.GetArchitectureName()); 1339554f68d3SGreg Clayton return true; 1340554f68d3SGreg Clayton } 1341554f68d3SGreg Clayton } 1342554f68d3SGreg Clayton } 1343554f68d3SGreg Clayton return false; 1344554f68d3SGreg Clayton 1345554f68d3SGreg Clayton case Entry::Type::ScriptTarget: 1346b9c1b51eSKate Stone if (exe_ctx) { 1347554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1348554f68d3SGreg Clayton if (target) 1349b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, target, 1350b9c1b51eSKate Stone entry.string.c_str()); 1351554f68d3SGreg Clayton } 1352554f68d3SGreg Clayton return false; 1353554f68d3SGreg Clayton 1354554f68d3SGreg Clayton case Entry::Type::ModuleFile: 1355b9c1b51eSKate Stone if (sc) { 1356554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1357b9c1b51eSKate Stone if (module) { 1358554f68d3SGreg Clayton if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1359554f68d3SGreg Clayton return true; 1360554f68d3SGreg Clayton } 1361554f68d3SGreg Clayton } 1362554f68d3SGreg Clayton return false; 1363554f68d3SGreg Clayton 1364554f68d3SGreg Clayton case Entry::Type::File: 1365b9c1b51eSKate Stone if (sc) { 1366554f68d3SGreg Clayton CompileUnit *cu = sc->comp_unit; 1367b9c1b51eSKate Stone if (cu) { 1368554f68d3SGreg Clayton // CompileUnit is a FileSpec 1369554f68d3SGreg Clayton if (DumpFile(s, *cu, (FileKind)entry.number)) 1370554f68d3SGreg Clayton return true; 1371554f68d3SGreg Clayton } 1372554f68d3SGreg Clayton } 1373554f68d3SGreg Clayton return false; 1374554f68d3SGreg Clayton 1375dc975670SDawn Perchik case Entry::Type::Lang: 1376b9c1b51eSKate Stone if (sc) { 1377dc975670SDawn Perchik CompileUnit *cu = sc->comp_unit; 1378b9c1b51eSKate Stone if (cu) { 1379b9c1b51eSKate Stone const char *lang_name = 1380b9c1b51eSKate Stone Language::GetNameForLanguageType(cu->GetLanguage()); 1381b9c1b51eSKate Stone if (lang_name) { 1382dc975670SDawn Perchik s.PutCString(lang_name); 1383dc975670SDawn Perchik return true; 1384dc975670SDawn Perchik } 1385dc975670SDawn Perchik } 1386dc975670SDawn Perchik } 1387dc975670SDawn Perchik return false; 1388dc975670SDawn Perchik 1389554f68d3SGreg Clayton case Entry::Type::FrameIndex: 1390b9c1b51eSKate Stone if (exe_ctx) { 1391554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1392b9c1b51eSKate Stone if (frame) { 1393554f68d3SGreg Clayton const char *format = "%" PRIu32; 1394554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1395554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1396554f68d3SGreg Clayton s.Printf(format, frame->GetFrameIndex()); 1397554f68d3SGreg Clayton return true; 1398554f68d3SGreg Clayton } 1399554f68d3SGreg Clayton } 1400554f68d3SGreg Clayton return false; 1401554f68d3SGreg Clayton 1402554f68d3SGreg Clayton case Entry::Type::FrameRegisterPC: 1403b9c1b51eSKate Stone if (exe_ctx) { 1404554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1405b9c1b51eSKate Stone if (frame) { 1406554f68d3SGreg Clayton const Address &pc_addr = frame->GetFrameCodeAddress(); 1407b9c1b51eSKate Stone if (pc_addr.IsValid()) { 1408554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) 1409554f68d3SGreg Clayton return true; 1410554f68d3SGreg Clayton } 1411554f68d3SGreg Clayton } 1412554f68d3SGreg Clayton } 1413554f68d3SGreg Clayton return false; 1414554f68d3SGreg Clayton 1415554f68d3SGreg Clayton case Entry::Type::FrameRegisterSP: 1416b9c1b51eSKate Stone if (exe_ctx) { 1417554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1418b9c1b51eSKate Stone if (frame) { 1419b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 1420b9c1b51eSKate Stone (lldb::Format)entry.number)) 1421554f68d3SGreg Clayton return true; 1422554f68d3SGreg Clayton } 1423554f68d3SGreg Clayton } 1424554f68d3SGreg Clayton return false; 1425554f68d3SGreg Clayton 1426554f68d3SGreg Clayton case Entry::Type::FrameRegisterFP: 1427b9c1b51eSKate Stone if (exe_ctx) { 1428554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1429b9c1b51eSKate Stone if (frame) { 1430b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, 1431b9c1b51eSKate Stone (lldb::Format)entry.number)) 1432554f68d3SGreg Clayton return true; 1433554f68d3SGreg Clayton } 1434554f68d3SGreg Clayton } 1435554f68d3SGreg Clayton return false; 1436554f68d3SGreg Clayton 1437554f68d3SGreg Clayton case Entry::Type::FrameRegisterFlags: 1438b9c1b51eSKate Stone if (exe_ctx) { 1439554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1440b9c1b51eSKate Stone if (frame) { 1441b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, 1442b9c1b51eSKate Stone LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1443554f68d3SGreg Clayton return true; 1444554f68d3SGreg Clayton } 1445554f68d3SGreg Clayton } 1446554f68d3SGreg Clayton return false; 1447554f68d3SGreg Clayton 1448554f68d3SGreg Clayton case Entry::Type::FrameRegisterByName: 1449b9c1b51eSKate Stone if (exe_ctx) { 1450554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1451b9c1b51eSKate Stone if (frame) { 1452b9c1b51eSKate Stone if (DumpRegister(s, frame, entry.string.c_str(), 1453b9c1b51eSKate Stone (lldb::Format)entry.number)) 1454554f68d3SGreg Clayton return true; 1455554f68d3SGreg Clayton } 1456554f68d3SGreg Clayton } 1457554f68d3SGreg Clayton return false; 1458554f68d3SGreg Clayton 1459554f68d3SGreg Clayton case Entry::Type::ScriptFrame: 1460b9c1b51eSKate Stone if (exe_ctx) { 1461554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1462554f68d3SGreg Clayton if (frame) 1463b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, frame, 1464b9c1b51eSKate Stone entry.string.c_str()); 1465554f68d3SGreg Clayton } 1466554f68d3SGreg Clayton return false; 1467554f68d3SGreg Clayton 1468554f68d3SGreg Clayton case Entry::Type::FunctionID: 1469b9c1b51eSKate Stone if (sc) { 1470b9c1b51eSKate Stone if (sc->function) { 1471554f68d3SGreg Clayton s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1472554f68d3SGreg Clayton return true; 1473b9c1b51eSKate Stone } else if (sc->symbol) { 1474554f68d3SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 1475554f68d3SGreg Clayton return true; 1476554f68d3SGreg Clayton } 1477554f68d3SGreg Clayton } 1478554f68d3SGreg Clayton return false; 1479554f68d3SGreg Clayton 1480554f68d3SGreg Clayton case Entry::Type::FunctionDidChange: 1481554f68d3SGreg Clayton return function_changed; 1482554f68d3SGreg Clayton 1483554f68d3SGreg Clayton case Entry::Type::FunctionInitialFunction: 1484554f68d3SGreg Clayton return initial_function; 1485554f68d3SGreg Clayton 1486b9c1b51eSKate Stone case Entry::Type::FunctionName: { 1487d4129b47SEnrico Granata Language *language_plugin = nullptr; 1488d4129b47SEnrico Granata bool language_plugin_handled = false; 1489d4129b47SEnrico Granata StreamString ss; 1490d4129b47SEnrico Granata if (sc->function) 1491d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1492d4129b47SEnrico Granata else if (sc->symbol) 1493d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1494b9c1b51eSKate Stone if (language_plugin) { 1495b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1496b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); 1497d4129b47SEnrico Granata } 1498b9c1b51eSKate Stone if (language_plugin_handled) { 1499d4129b47SEnrico Granata s.PutCString(ss.GetData()); 1500d4129b47SEnrico Granata return true; 1501b9c1b51eSKate Stone } else { 1502a74f37a5SEugene Zelenko const char *name = nullptr; 1503554f68d3SGreg Clayton if (sc->function) 1504a74f37a5SEugene Zelenko name = sc->function->GetName().AsCString(nullptr); 1505554f68d3SGreg Clayton else if (sc->symbol) 1506a74f37a5SEugene Zelenko name = sc->symbol->GetName().AsCString(nullptr); 1507b9c1b51eSKate Stone if (name) { 1508554f68d3SGreg Clayton s.PutCString(name); 1509554f68d3SGreg Clayton 1510b9c1b51eSKate Stone if (sc->block) { 1511554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1512b9c1b51eSKate Stone if (inline_block) { 1513b9c1b51eSKate Stone const InlineFunctionInfo *inline_info = 1514b9c1b51eSKate Stone sc->block->GetInlinedFunctionInfo(); 1515b9c1b51eSKate Stone if (inline_info) { 1516554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1517ddaf6a72SGreg Clayton inline_info->GetName(sc->function->GetLanguage()).Dump(&s); 1518554f68d3SGreg Clayton } 1519554f68d3SGreg Clayton } 1520554f68d3SGreg Clayton } 1521554f68d3SGreg Clayton return true; 1522554f68d3SGreg Clayton } 1523554f68d3SGreg Clayton } 1524d4129b47SEnrico Granata } 1525554f68d3SGreg Clayton return false; 1526554f68d3SGreg Clayton 1527b9c1b51eSKate Stone case Entry::Type::FunctionNameNoArgs: { 1528d4129b47SEnrico Granata Language *language_plugin = nullptr; 1529d4129b47SEnrico Granata bool language_plugin_handled = false; 1530d4129b47SEnrico Granata StreamString ss; 1531d4129b47SEnrico Granata if (sc->function) 1532d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1533d4129b47SEnrico Granata else if (sc->symbol) 1534d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1535b9c1b51eSKate Stone if (language_plugin) { 1536b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1537b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, 1538d4129b47SEnrico Granata ss); 1539d4129b47SEnrico Granata } 1540b9c1b51eSKate Stone if (language_plugin_handled) { 1541d4129b47SEnrico Granata s.PutCString(ss.GetData()); 1542d4129b47SEnrico Granata return true; 1543b9c1b51eSKate Stone } else { 1544554f68d3SGreg Clayton ConstString name; 1545554f68d3SGreg Clayton if (sc->function) 1546ddaf6a72SGreg Clayton name = sc->function->GetNameNoArguments(); 1547554f68d3SGreg Clayton else if (sc->symbol) 1548ddaf6a72SGreg Clayton name = sc->symbol->GetNameNoArguments(); 1549b9c1b51eSKate Stone if (name) { 1550554f68d3SGreg Clayton s.PutCString(name.GetCString()); 1551554f68d3SGreg Clayton return true; 1552554f68d3SGreg Clayton } 1553554f68d3SGreg Clayton } 1554d4129b47SEnrico Granata } 1555554f68d3SGreg Clayton return false; 1556554f68d3SGreg Clayton 1557b9c1b51eSKate Stone case Entry::Type::FunctionNameWithArgs: { 1558d4129b47SEnrico Granata Language *language_plugin = nullptr; 1559d4129b47SEnrico Granata bool language_plugin_handled = false; 1560d4129b47SEnrico Granata StreamString ss; 1561d4129b47SEnrico Granata if (sc->function) 1562d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1563d4129b47SEnrico Granata else if (sc->symbol) 1564d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1565b9c1b51eSKate Stone if (language_plugin) { 1566b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1567b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); 1568d4129b47SEnrico Granata } 1569b9c1b51eSKate Stone if (language_plugin_handled) { 1570d4129b47SEnrico Granata s.PutCString(ss.GetData()); 1571d4129b47SEnrico Granata return true; 1572b9c1b51eSKate Stone } else { 1573554f68d3SGreg Clayton // Print the function name with arguments in it 1574b9c1b51eSKate Stone if (sc->function) { 1575b9c1b51eSKate Stone ExecutionContextScope *exe_scope = 1576b9c1b51eSKate Stone exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 1577a74f37a5SEugene Zelenko const char *cstr = sc->function->GetName().AsCString(nullptr); 1578b9c1b51eSKate Stone if (cstr) { 1579a74f37a5SEugene Zelenko const InlineFunctionInfo *inline_info = nullptr; 1580554f68d3SGreg Clayton VariableListSP variable_list_sp; 1581554f68d3SGreg Clayton bool get_function_vars = true; 1582b9c1b51eSKate Stone if (sc->block) { 1583554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1584554f68d3SGreg Clayton 1585b9c1b51eSKate Stone if (inline_block) { 1586554f68d3SGreg Clayton get_function_vars = false; 1587554f68d3SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 1588554f68d3SGreg Clayton if (inline_info) 1589554f68d3SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList(true); 1590554f68d3SGreg Clayton } 1591554f68d3SGreg Clayton } 1592554f68d3SGreg Clayton 1593b9c1b51eSKate Stone if (get_function_vars) { 1594b9c1b51eSKate Stone variable_list_sp = 1595b9c1b51eSKate Stone sc->function->GetBlock(true).GetBlockVariableList(true); 1596554f68d3SGreg Clayton } 1597554f68d3SGreg Clayton 1598b9c1b51eSKate Stone if (inline_info) { 1599554f68d3SGreg Clayton s.PutCString(cstr); 1600554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1601b9c1b51eSKate Stone cstr = 1602b9c1b51eSKate Stone inline_info->GetName(sc->function->GetLanguage()).GetCString(); 1603554f68d3SGreg Clayton } 1604554f68d3SGreg Clayton 1605554f68d3SGreg Clayton VariableList args; 1606554f68d3SGreg Clayton if (variable_list_sp) 1607b9c1b51eSKate Stone variable_list_sp->AppendVariablesWithScope( 1608b9c1b51eSKate Stone eValueTypeVariableArgument, args); 1609b9c1b51eSKate Stone if (args.GetSize() > 0) { 1610554f68d3SGreg Clayton const char *open_paren = strchr(cstr, '('); 1611554f68d3SGreg Clayton const char *close_paren = nullptr; 1612554f68d3SGreg Clayton const char *generic = strchr(cstr, '<'); 1613554f68d3SGreg Clayton // if before the arguments list begins there is a template sign 1614554f68d3SGreg Clayton // then scan to the end of the generic args before you try to find 1615554f68d3SGreg Clayton // the arguments list 1616b9c1b51eSKate Stone if (generic && open_paren && generic < open_paren) { 1617554f68d3SGreg Clayton int generic_depth = 1; 1618554f68d3SGreg Clayton ++generic; 1619b9c1b51eSKate Stone for (; *generic && generic_depth > 0; generic++) { 1620554f68d3SGreg Clayton if (*generic == '<') 1621554f68d3SGreg Clayton generic_depth++; 1622554f68d3SGreg Clayton if (*generic == '>') 1623554f68d3SGreg Clayton generic_depth--; 1624554f68d3SGreg Clayton } 1625554f68d3SGreg Clayton if (*generic) 1626554f68d3SGreg Clayton open_paren = strchr(generic, '('); 1627554f68d3SGreg Clayton else 1628554f68d3SGreg Clayton open_paren = nullptr; 1629554f68d3SGreg Clayton } 1630b9c1b51eSKate Stone if (open_paren) { 1631b9c1b51eSKate Stone if (IsToken(open_paren, "(anonymous namespace)")) { 1632b9c1b51eSKate Stone open_paren = 1633b9c1b51eSKate Stone strchr(open_paren + strlen("(anonymous namespace)"), '('); 1634554f68d3SGreg Clayton if (open_paren) 1635554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1636b9c1b51eSKate Stone } else 1637554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1638554f68d3SGreg Clayton } 1639554f68d3SGreg Clayton 1640554f68d3SGreg Clayton if (open_paren) 1641554f68d3SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 1642b9c1b51eSKate Stone else { 1643554f68d3SGreg Clayton s.PutCString(cstr); 1644554f68d3SGreg Clayton s.PutChar('('); 1645554f68d3SGreg Clayton } 1646554f68d3SGreg Clayton const size_t num_args = args.GetSize(); 1647b9c1b51eSKate Stone for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { 1648554f68d3SGreg Clayton std::string buffer; 1649554f68d3SGreg Clayton 1650554f68d3SGreg Clayton VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); 1651b9c1b51eSKate Stone ValueObjectSP var_value_sp( 1652b9c1b51eSKate Stone ValueObjectVariable::Create(exe_scope, var_sp)); 1653ad91c7ceSEnrico Granata StreamString ss; 1654554f68d3SGreg Clayton const char *var_representation = nullptr; 1655554f68d3SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 1656b9c1b51eSKate Stone if (var_value_sp->GetCompilerType().IsValid()) { 1657ad91c7ceSEnrico Granata if (var_value_sp && exe_scope->CalculateTarget()) 1658b9c1b51eSKate Stone var_value_sp = 1659b9c1b51eSKate Stone var_value_sp->GetQualifiedRepresentationIfAvailable( 1660b9c1b51eSKate Stone exe_scope->CalculateTarget() 1661b9c1b51eSKate Stone ->TargetProperties::GetPreferDynamicValue(), 1662b9c1b51eSKate Stone exe_scope->CalculateTarget() 1663b9c1b51eSKate Stone ->TargetProperties::GetEnableSyntheticValue()); 166499558cc4SGreg Clayton if (var_value_sp->GetCompilerType().IsAggregateType() && 1665b9c1b51eSKate Stone DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { 1666b9c1b51eSKate Stone static StringSummaryFormat format( 1667b9c1b51eSKate Stone TypeSummaryImpl::Flags() 1668554f68d3SGreg Clayton .SetHideItemNames(false) 1669554f68d3SGreg Clayton .SetShowMembersOneLiner(true), 1670554f68d3SGreg Clayton ""); 1671b9c1b51eSKate Stone format.FormatObject(var_value_sp.get(), buffer, 1672b9c1b51eSKate Stone TypeSummaryOptions()); 1673554f68d3SGreg Clayton var_representation = buffer.c_str(); 1674b9c1b51eSKate Stone } else 1675b9c1b51eSKate Stone var_value_sp->DumpPrintableRepresentation( 1676b9c1b51eSKate Stone ss, ValueObject::ValueObjectRepresentationStyle:: 1677b9c1b51eSKate Stone eValueObjectRepresentationStyleSummary, 1678ad91c7ceSEnrico Granata eFormatDefault, 1679*65d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eAllow, 1680ad91c7ceSEnrico Granata false); 1681ad91c7ceSEnrico Granata } 1682ad91c7ceSEnrico Granata 1683ad91c7ceSEnrico Granata if (ss.GetData() && ss.GetSize()) 1684ad91c7ceSEnrico Granata var_representation = ss.GetData(); 1685554f68d3SGreg Clayton if (arg_idx > 0) 1686554f68d3SGreg Clayton s.PutCString(", "); 1687b9c1b51eSKate Stone if (var_value_sp->GetError().Success()) { 1688554f68d3SGreg Clayton if (var_representation) 1689554f68d3SGreg Clayton s.Printf("%s=%s", var_name, var_representation); 1690554f68d3SGreg Clayton else 1691b9c1b51eSKate Stone s.Printf("%s=%s at %s", var_name, 1692b9c1b51eSKate Stone var_value_sp->GetTypeName().GetCString(), 1693b9c1b51eSKate Stone var_value_sp->GetLocationAsCString()); 1694b9c1b51eSKate Stone } else 1695554f68d3SGreg Clayton s.Printf("%s=<unavailable>", var_name); 1696554f68d3SGreg Clayton } 1697554f68d3SGreg Clayton 1698554f68d3SGreg Clayton if (close_paren) 1699554f68d3SGreg Clayton s.PutCString(close_paren); 1700554f68d3SGreg Clayton else 1701554f68d3SGreg Clayton s.PutChar(')'); 1702554f68d3SGreg Clayton 1703b9c1b51eSKate Stone } else { 1704554f68d3SGreg Clayton s.PutCString(cstr); 1705554f68d3SGreg Clayton } 1706554f68d3SGreg Clayton return true; 1707554f68d3SGreg Clayton } 1708b9c1b51eSKate Stone } else if (sc->symbol) { 1709a74f37a5SEugene Zelenko const char *cstr = sc->symbol->GetName().AsCString(nullptr); 1710b9c1b51eSKate Stone if (cstr) { 1711554f68d3SGreg Clayton s.PutCString(cstr); 1712554f68d3SGreg Clayton return true; 1713554f68d3SGreg Clayton } 1714554f68d3SGreg Clayton } 1715554f68d3SGreg Clayton } 1716d4129b47SEnrico Granata } 1717554f68d3SGreg Clayton return false; 1718554f68d3SGreg Clayton 1719554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffset: 1720b9c1b51eSKate Stone if (addr) { 1721b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, 1722b9c1b51eSKate Stone false)) 1723554f68d3SGreg Clayton return true; 1724554f68d3SGreg Clayton } 1725554f68d3SGreg Clayton return false; 1726554f68d3SGreg Clayton 1727554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffsetConcrete: 1728b9c1b51eSKate Stone if (addr) { 1729b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, 1730b9c1b51eSKate Stone true)) 1731554f68d3SGreg Clayton return true; 1732554f68d3SGreg Clayton } 1733554f68d3SGreg Clayton return false; 1734554f68d3SGreg Clayton 1735554f68d3SGreg Clayton case Entry::Type::FunctionLineOffset: 1736b9c1b51eSKate Stone return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1737b9c1b51eSKate Stone sc->line_entry.range.GetBaseAddress(), 1738b9c1b51eSKate Stone false, false, false)); 1739554f68d3SGreg Clayton 1740554f68d3SGreg Clayton case Entry::Type::FunctionPCOffset: 1741b9c1b51eSKate Stone if (exe_ctx) { 1742554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1743b9c1b51eSKate Stone if (frame) { 1744b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1745b9c1b51eSKate Stone frame->GetFrameCodeAddress(), false, 1746b9c1b51eSKate Stone false, false)) 1747554f68d3SGreg Clayton return true; 1748554f68d3SGreg Clayton } 1749554f68d3SGreg Clayton } 1750554f68d3SGreg Clayton return false; 1751554f68d3SGreg Clayton 1752c980fa92SJason Molenda case Entry::Type::FunctionChanged: 1753a74f37a5SEugene Zelenko return function_changed; 1754c980fa92SJason Molenda 1755b9c1b51eSKate Stone case Entry::Type::FunctionIsOptimized: { 17566ab659a9SJason Molenda bool is_optimized = false; 1757b9c1b51eSKate Stone if (sc->function && sc->function->GetIsOptimized()) { 17586ab659a9SJason Molenda is_optimized = true; 17596ab659a9SJason Molenda } 17606ab659a9SJason Molenda return is_optimized; 17616ab659a9SJason Molenda } 17626ab659a9SJason Molenda 1763c980fa92SJason Molenda case Entry::Type::FunctionInitial: 1764a74f37a5SEugene Zelenko return initial_function; 1765c980fa92SJason Molenda 1766554f68d3SGreg Clayton case Entry::Type::LineEntryFile: 1767b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1768554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1769b9c1b51eSKate Stone if (module) { 1770554f68d3SGreg Clayton if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1771554f68d3SGreg Clayton return true; 1772554f68d3SGreg Clayton } 1773554f68d3SGreg Clayton } 1774554f68d3SGreg Clayton return false; 1775554f68d3SGreg Clayton 1776554f68d3SGreg Clayton case Entry::Type::LineEntryLineNumber: 1777b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1778554f68d3SGreg Clayton const char *format = "%" PRIu32; 1779554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1780554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1781554f68d3SGreg Clayton s.Printf(format, sc->line_entry.line); 1782554f68d3SGreg Clayton return true; 1783554f68d3SGreg Clayton } 1784554f68d3SGreg Clayton return false; 1785554f68d3SGreg Clayton 1786554f68d3SGreg Clayton case Entry::Type::LineEntryStartAddress: 1787554f68d3SGreg Clayton case Entry::Type::LineEntryEndAddress: 1788b9c1b51eSKate Stone if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { 1789554f68d3SGreg Clayton Address addr = sc->line_entry.range.GetBaseAddress(); 1790554f68d3SGreg Clayton 1791554f68d3SGreg Clayton if (entry.type == Entry::Type::LineEntryEndAddress) 1792554f68d3SGreg Clayton addr.Slide(sc->line_entry.range.GetByteSize()); 1793554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, addr, false)) 1794554f68d3SGreg Clayton return true; 1795554f68d3SGreg Clayton } 1796554f68d3SGreg Clayton return false; 1797554f68d3SGreg Clayton 1798554f68d3SGreg Clayton case Entry::Type::CurrentPCArrow: 1799b9c1b51eSKate Stone if (addr && exe_ctx && exe_ctx->GetFramePtr()) { 1800b9c1b51eSKate Stone RegisterContextSP reg_ctx = 1801b9c1b51eSKate Stone exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1802b9c1b51eSKate Stone if (reg_ctx) { 1803554f68d3SGreg Clayton addr_t pc_loadaddr = reg_ctx->GetPC(); 1804b9c1b51eSKate Stone if (pc_loadaddr != LLDB_INVALID_ADDRESS) { 1805554f68d3SGreg Clayton Address pc; 1806554f68d3SGreg Clayton pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); 1807b9c1b51eSKate Stone if (pc == *addr) { 1808554f68d3SGreg Clayton s.Printf("-> "); 1809554f68d3SGreg Clayton return true; 1810554f68d3SGreg Clayton } 1811554f68d3SGreg Clayton } 1812554f68d3SGreg Clayton } 1813554f68d3SGreg Clayton s.Printf(" "); 1814554f68d3SGreg Clayton return true; 1815554f68d3SGreg Clayton } 1816554f68d3SGreg Clayton return false; 1817554f68d3SGreg Clayton } 1818554f68d3SGreg Clayton return false; 1819554f68d3SGreg Clayton } 1820554f68d3SGreg Clayton 1821b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames( 1822b9c1b51eSKate Stone Stream &s, const FormatEntity::Entry::Definition *parent) { 1823b9c1b51eSKate Stone if (parent->children) { 1824554f68d3SGreg Clayton const size_t n = parent->num_children; 1825b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1826554f68d3SGreg Clayton if (i > 0) 1827554f68d3SGreg Clayton s.PutCString(", "); 1828554f68d3SGreg Clayton s.Printf("\"%s\"", parent->children[i].name); 1829554f68d3SGreg Clayton } 1830554f68d3SGreg Clayton return true; 1831554f68d3SGreg Clayton } 1832554f68d3SGreg Clayton return false; 1833554f68d3SGreg Clayton } 1834554f68d3SGreg Clayton 1835b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str, 1836554f68d3SGreg Clayton const FormatEntity::Entry::Definition *parent, 1837b9c1b51eSKate Stone FormatEntity::Entry &entry) { 1838554f68d3SGreg Clayton Error error; 1839554f68d3SGreg Clayton 1840554f68d3SGreg Clayton const size_t sep_pos = format_str.find_first_of(".[:"); 1841b9c1b51eSKate Stone const char sep_char = 1842b9c1b51eSKate Stone (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1843554f68d3SGreg Clayton llvm::StringRef key = format_str.substr(0, sep_pos); 1844554f68d3SGreg Clayton 1845554f68d3SGreg Clayton const size_t n = parent->num_children; 1846b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1847554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1848b9c1b51eSKate Stone if (key.equals(entry_def->name) || entry_def->name[0] == '*') { 1849554f68d3SGreg Clayton llvm::StringRef value; 1850554f68d3SGreg Clayton if (sep_char) 1851b9c1b51eSKate Stone value = 1852b9c1b51eSKate Stone format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1853b9c1b51eSKate Stone switch (entry_def->type) { 1854554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentString: 18553a29f8b9SPavel Labath entry.string = format_str.str(); 1856554f68d3SGreg Clayton return error; // Success 1857554f68d3SGreg Clayton 1858554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentNumber: 1859554f68d3SGreg Clayton entry.number = entry_def->data; 1860554f68d3SGreg Clayton return error; // Success 1861554f68d3SGreg Clayton 1862554f68d3SGreg Clayton case FormatEntity::Entry::Type::InsertString: 1863554f68d3SGreg Clayton entry.type = entry_def->type; 1864554f68d3SGreg Clayton entry.string = entry_def->string; 1865554f68d3SGreg Clayton return error; // Success 1866554f68d3SGreg Clayton 1867554f68d3SGreg Clayton default: 1868554f68d3SGreg Clayton entry.type = entry_def->type; 1869554f68d3SGreg Clayton break; 1870554f68d3SGreg Clayton } 1871554f68d3SGreg Clayton 1872b9c1b51eSKate Stone if (value.empty()) { 1873b9c1b51eSKate Stone if (entry_def->type == FormatEntity::Entry::Type::Invalid) { 1874b9c1b51eSKate Stone if (entry_def->children) { 1875554f68d3SGreg Clayton StreamString error_strm; 1876b9c1b51eSKate Stone error_strm.Printf("'%s' can't be specified on its own, you must " 1877b9c1b51eSKate Stone "access one of its children: ", 1878b9c1b51eSKate Stone entry_def->name); 1879554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, entry_def); 1880b9c1b51eSKate Stone error.SetErrorStringWithFormat("%s", 1881b9c1b51eSKate Stone error_strm.GetString().c_str()); 1882b9c1b51eSKate Stone } else if (sep_char == ':') { 1883b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1884b9c1b51eSKate Stone // string argument 1885554f68d3SGreg Clayton // that needs to be stored in the entry (like "${script.var:}"). 1886554f68d3SGreg Clayton // In this case the string value is the empty string which is ok. 1887b9c1b51eSKate Stone } else { 1888554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1889554f68d3SGreg Clayton } 1890554f68d3SGreg Clayton } 1891b9c1b51eSKate Stone } else { 1892b9c1b51eSKate Stone if (entry_def->children) { 1893554f68d3SGreg Clayton error = ParseEntry(value, entry_def, entry); 1894b9c1b51eSKate Stone } else if (sep_char == ':') { 1895b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1896b9c1b51eSKate Stone // string argument 1897b9c1b51eSKate Stone // that needs to be stored in the entry (like 1898b9c1b51eSKate Stone // "${script.var:modulename.function}") 18993a29f8b9SPavel Labath entry.string = value.str(); 1900b9c1b51eSKate Stone } else { 1901b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1902b9c1b51eSKate Stone "'%s' followed by '%s' but it has no children", key.str().c_str(), 1903554f68d3SGreg Clayton value.str().c_str()); 1904554f68d3SGreg Clayton } 1905554f68d3SGreg Clayton } 1906554f68d3SGreg Clayton return error; 1907554f68d3SGreg Clayton } 1908554f68d3SGreg Clayton } 1909554f68d3SGreg Clayton StreamString error_strm; 1910554f68d3SGreg Clayton if (parent->type == FormatEntity::Entry::Type::Root) 1911b9c1b51eSKate Stone error_strm.Printf( 1912b9c1b51eSKate Stone "invalid top level item '%s'. Valid top level items are: ", 1913b9c1b51eSKate Stone key.str().c_str()); 1914554f68d3SGreg Clayton else 1915b9c1b51eSKate Stone error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", 1916b9c1b51eSKate Stone key.str().c_str(), parent->name); 1917554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, parent); 1918554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); 1919554f68d3SGreg Clayton return error; 1920554f68d3SGreg Clayton } 1921554f68d3SGreg Clayton 1922554f68d3SGreg Clayton static const FormatEntity::Entry::Definition * 1923b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str, 1924b9c1b51eSKate Stone const FormatEntity::Entry::Definition *parent, 1925b9c1b51eSKate Stone llvm::StringRef &remainder) { 1926554f68d3SGreg Clayton Error error; 1927554f68d3SGreg Clayton 1928554f68d3SGreg Clayton std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 1929554f68d3SGreg Clayton const size_t n = parent->num_children; 1930b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1931554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1932b9c1b51eSKate Stone if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { 1933b9c1b51eSKate Stone if (p.second.empty()) { 1934554f68d3SGreg Clayton if (format_str.back() == '.') 1935554f68d3SGreg Clayton remainder = format_str.drop_front(format_str.size() - 1); 1936554f68d3SGreg Clayton else 1937554f68d3SGreg Clayton remainder = llvm::StringRef(); // Exact match 1938554f68d3SGreg Clayton return entry_def; 1939b9c1b51eSKate Stone } else { 1940b9c1b51eSKate Stone if (entry_def->children) { 1941554f68d3SGreg Clayton return FindEntry(p.second, entry_def, remainder); 1942b9c1b51eSKate Stone } else { 1943554f68d3SGreg Clayton remainder = p.second; 1944554f68d3SGreg Clayton return entry_def; 1945554f68d3SGreg Clayton } 1946554f68d3SGreg Clayton } 1947554f68d3SGreg Clayton } 1948554f68d3SGreg Clayton } 1949554f68d3SGreg Clayton remainder = format_str; 1950554f68d3SGreg Clayton return parent; 1951554f68d3SGreg Clayton } 1952554f68d3SGreg Clayton 1953b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, 1954b9c1b51eSKate Stone uint32_t depth) { 1955554f68d3SGreg Clayton Error error; 1956b9c1b51eSKate Stone while (!format.empty() && error.Success()) { 1957554f68d3SGreg Clayton const size_t non_special_chars = format.find_first_of("${}\\"); 1958554f68d3SGreg Clayton 1959b9c1b51eSKate Stone if (non_special_chars == llvm::StringRef::npos) { 1960554f68d3SGreg Clayton // No special characters, just string bytes so add them and we are done 1961554f68d3SGreg Clayton parent_entry.AppendText(format); 1962554f68d3SGreg Clayton return error; 1963554f68d3SGreg Clayton } 1964554f68d3SGreg Clayton 1965b9c1b51eSKate Stone if (non_special_chars > 0) { 1966b9c1b51eSKate Stone // We have a special character, so add all characters before these as a 1967b9c1b51eSKate Stone // plain string 1968554f68d3SGreg Clayton parent_entry.AppendText(format.substr(0, non_special_chars)); 1969554f68d3SGreg Clayton format = format.drop_front(non_special_chars); 1970554f68d3SGreg Clayton } 1971554f68d3SGreg Clayton 1972b9c1b51eSKate Stone switch (format[0]) { 1973554f68d3SGreg Clayton case '\0': 1974554f68d3SGreg Clayton return error; 1975554f68d3SGreg Clayton 1976b9c1b51eSKate Stone case '{': { 1977554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 1978554f68d3SGreg Clayton Entry scope_entry(Entry::Type::Scope); 1979554f68d3SGreg Clayton error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); 1980554f68d3SGreg Clayton if (error.Fail()) 1981554f68d3SGreg Clayton return error; 1982554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(scope_entry)); 1983b9c1b51eSKate Stone } break; 1984554f68d3SGreg Clayton 1985554f68d3SGreg Clayton case '}': 1986554f68d3SGreg Clayton if (depth == 0) 1987554f68d3SGreg Clayton error.SetErrorString("unmatched '}' character"); 1988554f68d3SGreg Clayton else 1989b9c1b51eSKate Stone format = 1990b9c1b51eSKate Stone format 1991b9c1b51eSKate Stone .drop_front(); // Skip the '}' as we are at the end of the scope 1992554f68d3SGreg Clayton return error; 1993554f68d3SGreg Clayton 1994b9c1b51eSKate Stone case '\\': { 1995554f68d3SGreg Clayton format = format.drop_front(); // Skip the '\' character 1996b9c1b51eSKate Stone if (format.empty()) { 1997b9c1b51eSKate Stone error.SetErrorString( 1998b9c1b51eSKate Stone "'\\' character was not followed by another character"); 1999554f68d3SGreg Clayton return error; 2000554f68d3SGreg Clayton } 2001554f68d3SGreg Clayton 2002554f68d3SGreg Clayton const char desens_char = format[0]; 2003554f68d3SGreg Clayton format = format.drop_front(); // Skip the desensitized char character 2004b9c1b51eSKate Stone switch (desens_char) { 2005b9c1b51eSKate Stone case 'a': 2006b9c1b51eSKate Stone parent_entry.AppendChar('\a'); 2007b9c1b51eSKate Stone break; 2008b9c1b51eSKate Stone case 'b': 2009b9c1b51eSKate Stone parent_entry.AppendChar('\b'); 2010b9c1b51eSKate Stone break; 2011b9c1b51eSKate Stone case 'f': 2012b9c1b51eSKate Stone parent_entry.AppendChar('\f'); 2013b9c1b51eSKate Stone break; 2014b9c1b51eSKate Stone case 'n': 2015b9c1b51eSKate Stone parent_entry.AppendChar('\n'); 2016b9c1b51eSKate Stone break; 2017b9c1b51eSKate Stone case 'r': 2018b9c1b51eSKate Stone parent_entry.AppendChar('\r'); 2019b9c1b51eSKate Stone break; 2020b9c1b51eSKate Stone case 't': 2021b9c1b51eSKate Stone parent_entry.AppendChar('\t'); 2022b9c1b51eSKate Stone break; 2023b9c1b51eSKate Stone case 'v': 2024b9c1b51eSKate Stone parent_entry.AppendChar('\v'); 2025b9c1b51eSKate Stone break; 2026b9c1b51eSKate Stone case '\'': 2027b9c1b51eSKate Stone parent_entry.AppendChar('\''); 2028b9c1b51eSKate Stone break; 2029b9c1b51eSKate Stone case '\\': 2030b9c1b51eSKate Stone parent_entry.AppendChar('\\'); 2031b9c1b51eSKate Stone break; 2032554f68d3SGreg Clayton case '0': 2033554f68d3SGreg Clayton // 1 to 3 octal chars 2034554f68d3SGreg Clayton { 2035554f68d3SGreg Clayton // Make a string that can hold onto the initial zero char, 2036554f68d3SGreg Clayton // up to 3 octal digits, and a terminating NULL. 2037554f68d3SGreg Clayton char oct_str[5] = {0, 0, 0, 0, 0}; 2038554f68d3SGreg Clayton 2039554f68d3SGreg Clayton int i; 2040554f68d3SGreg Clayton for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) 2041554f68d3SGreg Clayton oct_str[i] = format[i]; 2042554f68d3SGreg Clayton 2043554f68d3SGreg Clayton // We don't want to consume the last octal character since 2044554f68d3SGreg Clayton // the main for loop will do this for us, so we advance p by 2045554f68d3SGreg Clayton // one less than i (even if i is zero) 2046554f68d3SGreg Clayton format = format.drop_front(i); 2047a74f37a5SEugene Zelenko unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); 2048b9c1b51eSKate Stone if (octal_value <= UINT8_MAX) { 2049554f68d3SGreg Clayton parent_entry.AppendChar((char)octal_value); 2050b9c1b51eSKate Stone } else { 2051554f68d3SGreg Clayton error.SetErrorString("octal number is larger than a single byte"); 2052554f68d3SGreg Clayton return error; 2053554f68d3SGreg Clayton } 2054554f68d3SGreg Clayton } 2055554f68d3SGreg Clayton break; 2056554f68d3SGreg Clayton 2057554f68d3SGreg Clayton case 'x': 2058554f68d3SGreg Clayton // hex number in the format 2059b9c1b51eSKate Stone if (isxdigit(format[0])) { 2060554f68d3SGreg Clayton // Make a string that can hold onto two hex chars plus a 2061554f68d3SGreg Clayton // NULL terminator 2062554f68d3SGreg Clayton char hex_str[3] = {0, 0, 0}; 2063554f68d3SGreg Clayton hex_str[0] = format[0]; 2064554f68d3SGreg Clayton 2065554f68d3SGreg Clayton format = format.drop_front(); 2066554f68d3SGreg Clayton 2067b9c1b51eSKate Stone if (isxdigit(format[0])) { 2068554f68d3SGreg Clayton hex_str[1] = format[0]; 2069554f68d3SGreg Clayton format = format.drop_front(); 2070554f68d3SGreg Clayton } 2071554f68d3SGreg Clayton 2072a74f37a5SEugene Zelenko unsigned long hex_value = strtoul(hex_str, nullptr, 16); 2073b9c1b51eSKate Stone if (hex_value <= UINT8_MAX) { 2074554f68d3SGreg Clayton parent_entry.AppendChar((char)hex_value); 2075b9c1b51eSKate Stone } else { 2076554f68d3SGreg Clayton error.SetErrorString("hex number is larger than a single byte"); 2077554f68d3SGreg Clayton return error; 2078554f68d3SGreg Clayton } 2079b9c1b51eSKate Stone } else { 2080554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2081554f68d3SGreg Clayton } 2082554f68d3SGreg Clayton break; 2083554f68d3SGreg Clayton 2084554f68d3SGreg Clayton default: 2085554f68d3SGreg Clayton // Just desensitize any other character by just printing what 2086554f68d3SGreg Clayton // came after the '\' 2087554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2088554f68d3SGreg Clayton break; 2089554f68d3SGreg Clayton } 2090b9c1b51eSKate Stone } break; 2091554f68d3SGreg Clayton 2092554f68d3SGreg Clayton case '$': 2093b9c1b51eSKate Stone if (format.size() == 1) { 2094554f68d3SGreg Clayton // '$' at the end of a format string, just print the '$' 2095554f68d3SGreg Clayton parent_entry.AppendText("$"); 2096b9c1b51eSKate Stone } else { 2097554f68d3SGreg Clayton format = format.drop_front(); // Skip the '$' 2098554f68d3SGreg Clayton 2099b9c1b51eSKate Stone if (format[0] == '{') { 2100554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2101554f68d3SGreg Clayton 2102554f68d3SGreg Clayton llvm::StringRef variable, variable_format; 2103b9c1b51eSKate Stone error = FormatEntity::ExtractVariableInfo(format, variable, 2104b9c1b51eSKate Stone variable_format); 2105554f68d3SGreg Clayton if (error.Fail()) 2106554f68d3SGreg Clayton return error; 2107554f68d3SGreg Clayton bool verify_is_thread_id = false; 2108554f68d3SGreg Clayton Entry entry; 2109b9c1b51eSKate Stone if (!variable_format.empty()) { 21103a29f8b9SPavel Labath entry.printf_format = variable_format.str(); 2111554f68d3SGreg Clayton 2112554f68d3SGreg Clayton // If the format contains a '%' we are going to assume this is 2113554f68d3SGreg Clayton // a printf style format. So if you want to format your thread ID 2114554f68d3SGreg Clayton // using "0x%llx" you can use: 2115554f68d3SGreg Clayton // ${thread.id%0x%llx} 2116554f68d3SGreg Clayton // 2117554f68d3SGreg Clayton // If there is no '%' in the format, then it is assumed to be a 2118554f68d3SGreg Clayton // LLDB format name, or one of the extended formats specified in 2119554f68d3SGreg Clayton // the switch statement below. 2120554f68d3SGreg Clayton 2121b9c1b51eSKate Stone if (entry.printf_format.find('%') == std::string::npos) { 2122554f68d3SGreg Clayton bool clear_printf = false; 2123554f68d3SGreg Clayton 2124b9c1b51eSKate Stone if (FormatManager::GetFormatFromCString( 2125b9c1b51eSKate Stone entry.printf_format.c_str(), false, entry.fmt)) { 2126554f68d3SGreg Clayton // We have an LLDB format, so clear the printf format 2127554f68d3SGreg Clayton clear_printf = true; 2128b9c1b51eSKate Stone } else if (entry.printf_format.size() == 1) { 2129b9c1b51eSKate Stone switch (entry.printf_format[0]) { 2130554f68d3SGreg Clayton case '@': // if this is an @ sign, print ObjC description 2131b9c1b51eSKate Stone entry.number = ValueObject:: 2132b9c1b51eSKate Stone eValueObjectRepresentationStyleLanguageSpecific; 2133554f68d3SGreg Clayton clear_printf = true; 2134554f68d3SGreg Clayton break; 2135b9c1b51eSKate Stone case 'V': // if this is a V, print the value using the default 2136b9c1b51eSKate Stone // format 2137b9c1b51eSKate Stone entry.number = 2138b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2139554f68d3SGreg Clayton clear_printf = true; 2140554f68d3SGreg Clayton break; 2141554f68d3SGreg Clayton case 'L': // if this is an L, print the location of the value 2142b9c1b51eSKate Stone entry.number = 2143b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleLocation; 2144554f68d3SGreg Clayton clear_printf = true; 2145554f68d3SGreg Clayton break; 2146554f68d3SGreg Clayton case 'S': // if this is an S, print the summary after all 2147b9c1b51eSKate Stone entry.number = 2148b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2149554f68d3SGreg Clayton clear_printf = true; 2150554f68d3SGreg Clayton break; 2151554f68d3SGreg Clayton case '#': // if this is a '#', print the number of children 2152b9c1b51eSKate Stone entry.number = 2153b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleChildrenCount; 2154554f68d3SGreg Clayton clear_printf = true; 2155554f68d3SGreg Clayton break; 2156554f68d3SGreg Clayton case 'T': // if this is a 'T', print the type 2157b9c1b51eSKate Stone entry.number = 2158b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleType; 2159554f68d3SGreg Clayton clear_printf = true; 2160554f68d3SGreg Clayton break; 2161554f68d3SGreg Clayton case 'N': // if this is a 'N', print the name 2162b9c1b51eSKate Stone entry.number = 2163b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleName; 2164554f68d3SGreg Clayton clear_printf = true; 2165554f68d3SGreg Clayton break; 2166281b65bcSGreg Clayton case '>': // if this is a '>', print the expression path 2167b9c1b51eSKate Stone entry.number = ValueObject:: 2168b9c1b51eSKate Stone eValueObjectRepresentationStyleExpressionPath; 2169554f68d3SGreg Clayton clear_printf = true; 2170554f68d3SGreg Clayton break; 2171554f68d3SGreg Clayton default: 2172b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2173b9c1b51eSKate Stone entry.printf_format.c_str()); 2174554f68d3SGreg Clayton return error; 2175554f68d3SGreg Clayton } 2176b9c1b51eSKate Stone } else if (FormatManager::GetFormatFromCString( 2177b9c1b51eSKate Stone entry.printf_format.c_str(), true, entry.fmt)) { 2178554f68d3SGreg Clayton clear_printf = true; 2179b9c1b51eSKate Stone } else if (entry.printf_format == "tid") { 2180554f68d3SGreg Clayton verify_is_thread_id = true; 2181b9c1b51eSKate Stone } else { 2182b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2183b9c1b51eSKate Stone entry.printf_format.c_str()); 2184554f68d3SGreg Clayton return error; 2185554f68d3SGreg Clayton } 2186554f68d3SGreg Clayton 2187554f68d3SGreg Clayton // Our format string turned out to not be a printf style format 2188554f68d3SGreg Clayton // so lets clear the string 2189554f68d3SGreg Clayton if (clear_printf) 2190554f68d3SGreg Clayton entry.printf_format.clear(); 2191554f68d3SGreg Clayton } 2192554f68d3SGreg Clayton } 2193554f68d3SGreg Clayton 2194554f68d3SGreg Clayton // Check for dereferences 2195b9c1b51eSKate Stone if (variable[0] == '*') { 2196554f68d3SGreg Clayton entry.deref = true; 2197554f68d3SGreg Clayton variable = variable.drop_front(); 2198554f68d3SGreg Clayton } 2199554f68d3SGreg Clayton 2200554f68d3SGreg Clayton error = ParseEntry(variable, &g_root, entry); 2201554f68d3SGreg Clayton if (error.Fail()) 2202554f68d3SGreg Clayton return error; 2203554f68d3SGreg Clayton 2204b9c1b51eSKate Stone if (verify_is_thread_id) { 2205554f68d3SGreg Clayton if (entry.type != Entry::Type::ThreadID && 2206b9c1b51eSKate Stone entry.type != Entry::Type::ThreadProtocolID) { 2207b9c1b51eSKate Stone error.SetErrorString("the 'tid' format can only be used on " 2208b9c1b51eSKate Stone "${thread.id} and ${thread.protocol_id}"); 2209554f68d3SGreg Clayton } 2210554f68d3SGreg Clayton } 2211554f68d3SGreg Clayton 2212b9c1b51eSKate Stone switch (entry.type) { 2213554f68d3SGreg Clayton case Entry::Type::Variable: 2214554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 2215b9c1b51eSKate Stone if (entry.number == 0) { 2216554f68d3SGreg Clayton if (entry.string.empty()) 2217b9c1b51eSKate Stone entry.number = 2218b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2219554f68d3SGreg Clayton else 2220b9c1b51eSKate Stone entry.number = 2221b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2222554f68d3SGreg Clayton } 2223554f68d3SGreg Clayton break; 2224554f68d3SGreg Clayton default: 2225b9c1b51eSKate Stone // Make sure someone didn't try to dereference anything but ${var} 2226b9c1b51eSKate Stone // or ${svar} 2227b9c1b51eSKate Stone if (entry.deref) { 2228b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2229b9c1b51eSKate Stone "${%s} can't be dereferenced, only ${var} and ${svar} can.", 2230b9c1b51eSKate Stone variable.str().c_str()); 2231554f68d3SGreg Clayton return error; 2232554f68d3SGreg Clayton } 2233554f68d3SGreg Clayton } 2234554f68d3SGreg Clayton // Check if this entry just wants to insert a constant string 2235554f68d3SGreg Clayton // value into the parent_entry, if so, insert the string with 2236554f68d3SGreg Clayton // AppendText, else append the entry to the parent_entry. 2237554f68d3SGreg Clayton if (entry.type == Entry::Type::InsertString) 2238554f68d3SGreg Clayton parent_entry.AppendText(entry.string.c_str()); 2239554f68d3SGreg Clayton else 2240554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(entry)); 2241554f68d3SGreg Clayton } 2242554f68d3SGreg Clayton } 2243554f68d3SGreg Clayton break; 2244554f68d3SGreg Clayton } 2245554f68d3SGreg Clayton } 2246554f68d3SGreg Clayton return error; 2247554f68d3SGreg Clayton } 2248554f68d3SGreg Clayton 2249b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, 2250b9c1b51eSKate Stone llvm::StringRef &variable_name, 2251b9c1b51eSKate Stone llvm::StringRef &variable_format) { 2252554f68d3SGreg Clayton Error error; 2253554f68d3SGreg Clayton variable_name = llvm::StringRef(); 2254554f68d3SGreg Clayton variable_format = llvm::StringRef(); 2255554f68d3SGreg Clayton 2256e8433cc1SBruce Mitchener const size_t paren_pos = format_str.find('}'); 2257b9c1b51eSKate Stone if (paren_pos != llvm::StringRef::npos) { 2258e8433cc1SBruce Mitchener const size_t percent_pos = format_str.find('%'); 2259b9c1b51eSKate Stone if (percent_pos < paren_pos) { 2260b9c1b51eSKate Stone if (percent_pos > 0) { 2261554f68d3SGreg Clayton if (percent_pos > 1) 2262554f68d3SGreg Clayton variable_name = format_str.substr(0, percent_pos); 2263b9c1b51eSKate Stone variable_format = 2264b9c1b51eSKate Stone format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2265554f68d3SGreg Clayton } 2266b9c1b51eSKate Stone } else { 2267554f68d3SGreg Clayton variable_name = format_str.substr(0, paren_pos); 2268554f68d3SGreg Clayton } 2269554f68d3SGreg Clayton // Strip off elements and the formatting and the trailing '}' 2270554f68d3SGreg Clayton format_str = format_str.substr(paren_pos + 1); 2271b9c1b51eSKate Stone } else { 2272b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2273b9c1b51eSKate Stone "missing terminating '}' character for '${%s'", 2274b9c1b51eSKate Stone format_str.str().c_str()); 2275554f68d3SGreg Clayton } 2276554f68d3SGreg Clayton return error; 2277554f68d3SGreg Clayton } 2278554f68d3SGreg Clayton 2279b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, 2280b9c1b51eSKate Stone llvm::StringRef variable_name, 2281b9c1b51eSKate Stone llvm::StringRef variable_format) { 2282b9c1b51eSKate Stone if (variable_name.empty() || variable_name.equals(".fullpath")) { 2283554f68d3SGreg Clayton file_spec.Dump(&s); 2284554f68d3SGreg Clayton return true; 2285b9c1b51eSKate Stone } else if (variable_name.equals(".basename")) { 2286554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2287554f68d3SGreg Clayton return true; 2288b9c1b51eSKate Stone } else if (variable_name.equals(".dirname")) { 2289554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2290554f68d3SGreg Clayton return true; 2291554f68d3SGreg Clayton } 2292554f68d3SGreg Clayton return false; 2293554f68d3SGreg Clayton } 2294554f68d3SGreg Clayton 2295b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix, 2296b9c1b51eSKate Stone const char *suffix) { 2297554f68d3SGreg Clayton std::string match(prefix.str()); 2298554f68d3SGreg Clayton match.append(suffix); 22993a29f8b9SPavel Labath return match; 2300554f68d3SGreg Clayton } 2301554f68d3SGreg Clayton 2302b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def, 2303554f68d3SGreg Clayton const llvm::StringRef &prefix, 2304554f68d3SGreg Clayton const llvm::StringRef &match_prefix, 2305b9c1b51eSKate Stone StringList &matches) { 2306554f68d3SGreg Clayton const size_t n = def->num_children; 2307b9c1b51eSKate Stone if (n > 0) { 2308b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 23093a29f8b9SPavel Labath std::string match = prefix.str(); 2310554f68d3SGreg Clayton if (match_prefix.empty()) 2311554f68d3SGreg Clayton matches.AppendString(MakeMatch(prefix, def->children[i].name)); 2312b9c1b51eSKate Stone else if (strncmp(def->children[i].name, match_prefix.data(), 2313b9c1b51eSKate Stone match_prefix.size()) == 0) 2314b9c1b51eSKate Stone matches.AppendString( 2315b9c1b51eSKate Stone MakeMatch(prefix, def->children[i].name + match_prefix.size())); 2316554f68d3SGreg Clayton } 2317554f68d3SGreg Clayton } 2318554f68d3SGreg Clayton } 2319a74f37a5SEugene Zelenko 2320b9c1b51eSKate Stone size_t FormatEntity::AutoComplete(const char *s, int match_start_point, 2321b9c1b51eSKate Stone int max_return_elements, bool &word_complete, 2322b9c1b51eSKate Stone StringList &matches) { 2323554f68d3SGreg Clayton word_complete = false; 2324554f68d3SGreg Clayton llvm::StringRef str(s + match_start_point); 2325554f68d3SGreg Clayton matches.Clear(); 2326554f68d3SGreg Clayton 2327554f68d3SGreg Clayton const size_t dollar_pos = str.rfind('$'); 2328b9c1b51eSKate Stone if (dollar_pos != llvm::StringRef::npos) { 2329554f68d3SGreg Clayton // Hitting TAB after $ at the end of the string add a "{" 2330b9c1b51eSKate Stone if (dollar_pos == str.size() - 1) { 23313a29f8b9SPavel Labath std::string match = str.str(); 2332554f68d3SGreg Clayton match.append("{"); 2333554f68d3SGreg Clayton matches.AppendString(std::move(match)); 2334b9c1b51eSKate Stone } else if (str[dollar_pos + 1] == '{') { 2335554f68d3SGreg Clayton const size_t close_pos = str.find('}', dollar_pos + 2); 2336b9c1b51eSKate Stone if (close_pos == llvm::StringRef::npos) { 2337554f68d3SGreg Clayton const size_t format_pos = str.find('%', dollar_pos + 2); 2338b9c1b51eSKate Stone if (format_pos == llvm::StringRef::npos) { 2339554f68d3SGreg Clayton llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); 2340b9c1b51eSKate Stone if (partial_variable.empty()) { 2341554f68d3SGreg Clayton // Suggest all top level entites as we are just past "${" 2342554f68d3SGreg Clayton AddMatches(&g_root, str, llvm::StringRef(), matches); 2343b9c1b51eSKate Stone } else { 2344554f68d3SGreg Clayton // We have a partially specified variable, find it 2345554f68d3SGreg Clayton llvm::StringRef remainder; 2346b9c1b51eSKate Stone const FormatEntity::Entry::Definition *entry_def = 2347b9c1b51eSKate Stone FindEntry(partial_variable, &g_root, remainder); 2348b9c1b51eSKate Stone if (entry_def) { 2349554f68d3SGreg Clayton const size_t n = entry_def->num_children; 2350554f68d3SGreg Clayton 2351b9c1b51eSKate Stone if (remainder.empty()) { 2352554f68d3SGreg Clayton // Exact match 2353b9c1b51eSKate Stone if (n > 0) { 2354554f68d3SGreg Clayton // "${thread.info" <TAB> 23553a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, ".")); 2356b9c1b51eSKate Stone } else { 2357554f68d3SGreg Clayton // "${thread.id" <TAB> 23583a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, "}")); 2359554f68d3SGreg Clayton word_complete = true; 2360554f68d3SGreg Clayton } 2361b9c1b51eSKate Stone } else if (remainder.equals(".")) { 2362554f68d3SGreg Clayton // "${thread." <TAB> 2363554f68d3SGreg Clayton AddMatches(entry_def, str, llvm::StringRef(), matches); 2364b9c1b51eSKate Stone } else { 2365554f68d3SGreg Clayton // We have a partial match 2366554f68d3SGreg Clayton // "${thre" <TAB> 2367554f68d3SGreg Clayton AddMatches(entry_def, str, remainder, matches); 2368554f68d3SGreg Clayton } 2369554f68d3SGreg Clayton } 2370554f68d3SGreg Clayton } 2371554f68d3SGreg Clayton } 2372554f68d3SGreg Clayton } 2373554f68d3SGreg Clayton } 2374554f68d3SGreg Clayton } 2375554f68d3SGreg Clayton return matches.GetSize(); 2376554f68d3SGreg Clayton } 2377