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/ValueObject.h" 23554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 24554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h" 25554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h" 26ad91c7ceSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h" 27937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h" 28554f68d3SGreg Clayton #include "lldb/Host/FileSpec.h" 29554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 30554f68d3SGreg Clayton #include "lldb/Symbol/Block.h" 31554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 32554f68d3SGreg Clayton #include "lldb/Symbol/Function.h" 33554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h" 34554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h" 35554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h" 36554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h" 370e0984eeSJim Ingham #include "lldb/Target/Language.h" 38554f68d3SGreg Clayton #include "lldb/Target/Process.h" 39554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h" 40554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h" 41554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h" 42554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h" 43554f68d3SGreg Clayton #include "lldb/Target/Target.h" 44554f68d3SGreg Clayton #include "lldb/Target/Thread.h" 45554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 46bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 47bf9a7730SZachary Turner #include "lldb/Utility/StreamString.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, \ 67*e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 68*e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \ 69b9c1b51eSKate Stone } 70b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \ 71b9c1b51eSKate Stone { \ 72b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 73*e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 74*e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, 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), 1006a9767c7SJim Ingham ENTRY("no-debug", FrameNoDebug, None), 101554f68d3SGreg Clayton ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), 102554f68d3SGreg Clayton }; 103554f68d3SGreg Clayton 104b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = { 105b9c1b51eSKate Stone ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString), 106554f68d3SGreg Clayton ENTRY("name-without-args", FunctionNameNoArgs, CString), 107554f68d3SGreg Clayton ENTRY("name-with-args", FunctionNameWithArgs, CString), 108554f68d3SGreg Clayton ENTRY("addr-offset", FunctionAddrOffset, UInt64), 109b9c1b51eSKate Stone ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, 110b9c1b51eSKate Stone UInt64), 111554f68d3SGreg Clayton ENTRY("line-offset", FunctionLineOffset, UInt64), 112c980fa92SJason Molenda ENTRY("pc-offset", FunctionPCOffset, UInt64), 113c980fa92SJason Molenda ENTRY("initial-function", FunctionInitial, None), 1146ab659a9SJason Molenda ENTRY("changed", FunctionChanged, None), 115b9c1b51eSKate Stone ENTRY("is-optimized", FunctionIsOptimized, None)}; 116554f68d3SGreg Clayton 117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = { 118554f68d3SGreg Clayton ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), 119554f68d3SGreg Clayton ENTRY("number", LineEntryLineNumber, UInt32), 120554f68d3SGreg Clayton ENTRY("start-addr", LineEntryStartAddress, UInt64), 121554f68d3SGreg Clayton ENTRY("end-addr", LineEntryEndAddress, UInt64), 122554f68d3SGreg Clayton }; 123554f68d3SGreg Clayton 124b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = { 125554f68d3SGreg Clayton ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), 126554f68d3SGreg Clayton }; 127554f68d3SGreg Clayton 128b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = { 129554f68d3SGreg Clayton ENTRY("id", ProcessID, UInt64), 130554f68d3SGreg Clayton ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename), 131554f68d3SGreg Clayton ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries), 132554f68d3SGreg Clayton }; 133554f68d3SGreg Clayton 134b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = { 135b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 136554f68d3SGreg Clayton 137b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = { 138b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 139554f68d3SGreg Clayton 140b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = { 141554f68d3SGreg Clayton ENTRY("id", ThreadID, UInt64), 142554f68d3SGreg Clayton ENTRY("protocol_id", ThreadProtocolID, UInt64), 143554f68d3SGreg Clayton ENTRY("index", ThreadIndexID, UInt32), 144554f68d3SGreg Clayton ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry), 145554f68d3SGreg Clayton ENTRY("queue", ThreadQueue, CString), 146554f68d3SGreg Clayton ENTRY("name", ThreadName, CString), 147554f68d3SGreg Clayton ENTRY("stop-reason", ThreadStopReason, CString), 148554f68d3SGreg Clayton ENTRY("return-value", ThreadReturnValue, CString), 149554f68d3SGreg Clayton ENTRY("completed-expression", ThreadCompletedExpression, CString), 150554f68d3SGreg Clayton }; 151554f68d3SGreg Clayton 152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = { 153554f68d3SGreg Clayton ENTRY("arch", TargetArch, CString), 154554f68d3SGreg Clayton }; 155554f68d3SGreg Clayton 156554f68d3SGreg Clayton #define _TO_STR2(_val) #_val 157554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val) 158554f68d3SGreg Clayton 159b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { 160b9c1b51eSKate Stone ENTRY_STRING("black", 161b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 162554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 163b9c1b51eSKate Stone ENTRY_STRING("green", 164b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 165b9c1b51eSKate Stone ENTRY_STRING("yellow", 166b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 167b9c1b51eSKate Stone ENTRY_STRING("blue", 168b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 169b9c1b51eSKate Stone ENTRY_STRING("purple", 170b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 171b9c1b51eSKate Stone ENTRY_STRING("cyan", 172b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 173b9c1b51eSKate Stone ENTRY_STRING("white", 174b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 175554f68d3SGreg Clayton }; 176554f68d3SGreg Clayton 177b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { 178b9c1b51eSKate Stone ENTRY_STRING("black", 179b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 180554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 181b9c1b51eSKate Stone ENTRY_STRING("green", 182b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 183b9c1b51eSKate Stone ENTRY_STRING("yellow", 184b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 185b9c1b51eSKate Stone ENTRY_STRING("blue", 186b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 187b9c1b51eSKate Stone ENTRY_STRING("purple", 188b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 189b9c1b51eSKate Stone ENTRY_STRING("cyan", 190b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 191b9c1b51eSKate Stone ENTRY_STRING("white", 192b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 193554f68d3SGreg Clayton }; 194554f68d3SGreg Clayton 195b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = { 196554f68d3SGreg Clayton ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries), 197554f68d3SGreg Clayton ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries), 198b9c1b51eSKate Stone ENTRY_STRING("normal", 199b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 200554f68d3SGreg Clayton ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 201554f68d3SGreg Clayton ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 202b9c1b51eSKate Stone ENTRY_STRING("italic", 203b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 204b9c1b51eSKate Stone ENTRY_STRING("underline", 205b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 206b9c1b51eSKate Stone ENTRY_STRING("slow-blink", 207b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 208b9c1b51eSKate Stone ENTRY_STRING("fast-blink", 209b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 210b9c1b51eSKate Stone ENTRY_STRING("negative", 211b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 212b9c1b51eSKate Stone ENTRY_STRING("conceal", 213b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 214b9c1b51eSKate Stone ENTRY_STRING("crossed-out", 215b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 216554f68d3SGreg Clayton }; 217554f68d3SGreg Clayton 218b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = { 219554f68d3SGreg Clayton ENTRY("frame", ScriptFrame, None), 220554f68d3SGreg Clayton ENTRY("process", ScriptProcess, None), 221554f68d3SGreg Clayton ENTRY("target", ScriptTarget, None), 222554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 223554f68d3SGreg Clayton ENTRY("var", ScriptVariable, None), 224554f68d3SGreg Clayton ENTRY("svar", ScriptVariableSynthetic, None), 225554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 226554f68d3SGreg Clayton }; 227554f68d3SGreg Clayton 228b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = { 229554f68d3SGreg Clayton ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries), 230554f68d3SGreg Clayton ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64), 231554f68d3SGreg Clayton ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries), 232554f68d3SGreg Clayton ENTRY("current-pc-arrow", CurrentPCArrow, CString), 233554f68d3SGreg Clayton ENTRY_CHILDREN("file", File, CString, g_file_child_entries), 234dc975670SDawn Perchik ENTRY("language", Lang, CString), 235554f68d3SGreg Clayton ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries), 236554f68d3SGreg Clayton ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries), 237554f68d3SGreg Clayton ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries), 238554f68d3SGreg Clayton ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries), 239554f68d3SGreg Clayton ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries), 240554f68d3SGreg Clayton ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries), 241b9c1b51eSKate Stone ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None, 242b9c1b51eSKate Stone g_svar_child_entries), 243554f68d3SGreg Clayton ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries), 244554f68d3SGreg Clayton ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries), 245554f68d3SGreg Clayton ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries), 246554f68d3SGreg Clayton }; 247554f68d3SGreg Clayton 248b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root = 249b9c1b51eSKate Stone ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries); 250554f68d3SGreg Clayton 251b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s) 252b9c1b51eSKate Stone : string(s.data(), s.size()), printf_format(), children(), 253b9c1b51eSKate Stone definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), 254b9c1b51eSKate Stone number(0), deref(false) {} 255554f68d3SGreg Clayton 256b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch) 257b9c1b51eSKate Stone : string(1, ch), printf_format(), children(), definition(nullptr), 258b9c1b51eSKate Stone type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} 259554f68d3SGreg Clayton 260b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) { 261554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 262554f68d3SGreg Clayton children.push_back(Entry(ch)); 263554f68d3SGreg Clayton else 264554f68d3SGreg Clayton children.back().string.append(1, ch); 265554f68d3SGreg Clayton } 266554f68d3SGreg Clayton 267b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { 268554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 269554f68d3SGreg Clayton children.push_back(Entry(s)); 270554f68d3SGreg Clayton else 271554f68d3SGreg Clayton children.back().string.append(s.data(), s.size()); 272554f68d3SGreg Clayton } 273554f68d3SGreg Clayton 274b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) { 275554f68d3SGreg Clayton return AppendText(llvm::StringRef(cstr)); 276554f68d3SGreg Clayton } 277554f68d3SGreg Clayton 278b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { 279554f68d3SGreg Clayton entry.Clear(); 280554f68d3SGreg Clayton entry.type = Entry::Type::Root; 281554f68d3SGreg Clayton llvm::StringRef modifiable_format(format_str); 282554f68d3SGreg Clayton return ParseInternal(modifiable_format, entry, 0); 283554f68d3SGreg Clayton } 284554f68d3SGreg Clayton 285b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee) \ 286b9c1b51eSKate Stone case FormatEntity::Entry::Type::eee: \ 287b9c1b51eSKate Stone return #eee 288554f68d3SGreg Clayton 289b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) { 290b9c1b51eSKate Stone switch (t) { 291554f68d3SGreg Clayton ENUM_TO_CSTR(Invalid); 292554f68d3SGreg Clayton ENUM_TO_CSTR(ParentNumber); 293554f68d3SGreg Clayton ENUM_TO_CSTR(ParentString); 294554f68d3SGreg Clayton ENUM_TO_CSTR(InsertString); 295554f68d3SGreg Clayton ENUM_TO_CSTR(Root); 296554f68d3SGreg Clayton ENUM_TO_CSTR(String); 297554f68d3SGreg Clayton ENUM_TO_CSTR(Scope); 298554f68d3SGreg Clayton ENUM_TO_CSTR(Variable); 299554f68d3SGreg Clayton ENUM_TO_CSTR(VariableSynthetic); 300554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariable); 301554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariableSynthetic); 302554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoad); 303554f68d3SGreg Clayton ENUM_TO_CSTR(AddressFile); 304554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoadOrFile); 305554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessID); 306554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessFile); 307554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptProcess); 308554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadID); 309554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadProtocolID); 310554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadIndexID); 311554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadName); 312554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadQueue); 313554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadStopReason); 314554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadReturnValue); 315554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadCompletedExpression); 316554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptThread); 317554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadInfo); 318554f68d3SGreg Clayton ENUM_TO_CSTR(TargetArch); 319554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptTarget); 320554f68d3SGreg Clayton ENUM_TO_CSTR(ModuleFile); 321554f68d3SGreg Clayton ENUM_TO_CSTR(File); 322dc975670SDawn Perchik ENUM_TO_CSTR(Lang); 323554f68d3SGreg Clayton ENUM_TO_CSTR(FrameIndex); 3246a9767c7SJim Ingham ENUM_TO_CSTR(FrameNoDebug); 325554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterPC); 326554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterSP); 327554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFP); 328554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFlags); 329554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterByName); 330554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptFrame); 331554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionID); 332554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionDidChange); 333554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionInitialFunction); 334554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionName); 335554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameWithArgs); 336554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameNoArgs); 337554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffset); 338554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 339554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionLineOffset); 340554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionPCOffset); 341c980fa92SJason Molenda ENUM_TO_CSTR(FunctionInitial); 342c980fa92SJason Molenda ENUM_TO_CSTR(FunctionChanged); 3436ab659a9SJason Molenda ENUM_TO_CSTR(FunctionIsOptimized); 344554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryFile); 345554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryLineNumber); 346554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryStartAddress); 347554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryEndAddress); 348554f68d3SGreg Clayton ENUM_TO_CSTR(CurrentPCArrow); 349554f68d3SGreg Clayton } 350554f68d3SGreg Clayton return "???"; 351554f68d3SGreg Clayton } 352554f68d3SGreg Clayton 353554f68d3SGreg Clayton #undef ENUM_TO_CSTR 354554f68d3SGreg Clayton 355b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const { 356554f68d3SGreg Clayton s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 357554f68d3SGreg Clayton if (fmt != eFormatDefault) 358554f68d3SGreg Clayton s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); 359554f68d3SGreg Clayton if (!string.empty()) 360554f68d3SGreg Clayton s.Printf("string = \"%s\"", string.c_str()); 361554f68d3SGreg Clayton if (!printf_format.empty()) 362554f68d3SGreg Clayton s.Printf("printf_format = \"%s\"", printf_format.c_str()); 363554f68d3SGreg Clayton if (number != 0) 364554f68d3SGreg Clayton s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 365554f68d3SGreg Clayton if (deref) 366554f68d3SGreg Clayton s.Printf("deref = true, "); 367554f68d3SGreg Clayton s.EOL(); 368b9c1b51eSKate Stone for (const auto &child : children) { 369554f68d3SGreg Clayton child.Dump(s, depth + 1); 370554f68d3SGreg Clayton } 371554f68d3SGreg Clayton } 372554f68d3SGreg Clayton 373554f68d3SGreg Clayton template <typename T> 374b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, 375b9c1b51eSKate Stone const ExecutionContext *exe_ctx, T t, 376b9c1b51eSKate Stone const char *script_function_name) { 377554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 378554f68d3SGreg Clayton 379b9c1b51eSKate Stone if (target) { 380b9c1b51eSKate Stone ScriptInterpreter *script_interpreter = 381b9c1b51eSKate Stone target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 382b9c1b51eSKate Stone if (script_interpreter) { 383554f68d3SGreg Clayton Error error; 384554f68d3SGreg Clayton std::string script_output; 385554f68d3SGreg Clayton 386b9c1b51eSKate Stone if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, 387b9c1b51eSKate Stone script_output, error) && 388b9c1b51eSKate Stone error.Success()) { 389554f68d3SGreg Clayton s.Printf("%s", script_output.c_str()); 390554f68d3SGreg Clayton return true; 391b9c1b51eSKate Stone } else { 392554f68d3SGreg Clayton s.Printf("<error: %s>", error.AsCString()); 393554f68d3SGreg Clayton } 394554f68d3SGreg Clayton } 395554f68d3SGreg Clayton } 396554f68d3SGreg Clayton return false; 397554f68d3SGreg Clayton } 398554f68d3SGreg Clayton 399b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc, 400b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address &addr, 401b9c1b51eSKate Stone bool print_file_addr_or_load_addr) { 402554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 403554f68d3SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 404554f68d3SGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 405554f68d3SGreg Clayton vaddr = addr.GetLoadAddress(target); 406554f68d3SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 407554f68d3SGreg Clayton vaddr = addr.GetFileAddress(); 408554f68d3SGreg Clayton 409b9c1b51eSKate Stone if (vaddr != LLDB_INVALID_ADDRESS) { 410554f68d3SGreg Clayton int addr_width = 0; 411b9c1b51eSKate Stone if (exe_ctx && target) { 412554f68d3SGreg Clayton addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 413554f68d3SGreg Clayton } 414554f68d3SGreg Clayton if (addr_width == 0) 415554f68d3SGreg Clayton addr_width = 16; 416b9c1b51eSKate Stone if (print_file_addr_or_load_addr) { 417a74f37a5SEugene Zelenko ExecutionContextScope *exe_scope = nullptr; 418554f68d3SGreg Clayton if (exe_ctx) 419554f68d3SGreg Clayton exe_scope = exe_ctx->GetBestExecutionContextScope(); 420b9c1b51eSKate Stone addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, 421b9c1b51eSKate Stone Address::DumpStyleModuleWithFileAddress, 0); 422b9c1b51eSKate Stone } else { 423554f68d3SGreg Clayton s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 424554f68d3SGreg Clayton } 425554f68d3SGreg Clayton return true; 426554f68d3SGreg Clayton } 427554f68d3SGreg Clayton return false; 428554f68d3SGreg Clayton } 429554f68d3SGreg Clayton 430b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, 431554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 432554f68d3SGreg Clayton const Address &format_addr, 433b9c1b51eSKate Stone bool concrete_only, bool no_padding, 434b9c1b51eSKate Stone bool print_zero_offsets) { 435b9c1b51eSKate Stone if (format_addr.IsValid()) { 436554f68d3SGreg Clayton Address func_addr; 437554f68d3SGreg Clayton 438b9c1b51eSKate Stone if (sc) { 439b9c1b51eSKate Stone if (sc->function) { 440554f68d3SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 441b9c1b51eSKate Stone if (sc->block && !concrete_only) { 442554f68d3SGreg Clayton // Check to make sure we aren't in an inline 443554f68d3SGreg Clayton // function. If we are, use the inline block 444554f68d3SGreg Clayton // range that contains "format_addr" since 445554f68d3SGreg Clayton // blocks can be discontiguous. 446554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 447554f68d3SGreg Clayton AddressRange inline_range; 448b9c1b51eSKate Stone if (inline_block && 449b9c1b51eSKate Stone inline_block->GetRangeContainingAddress(format_addr, 450b9c1b51eSKate Stone inline_range)) 451554f68d3SGreg Clayton func_addr = inline_range.GetBaseAddress(); 452554f68d3SGreg Clayton } 453b9c1b51eSKate Stone } else if (sc->symbol && sc->symbol->ValueIsAddress()) 454358cf1eaSGreg Clayton func_addr = sc->symbol->GetAddressRef(); 455554f68d3SGreg Clayton } 456554f68d3SGreg Clayton 457b9c1b51eSKate Stone if (func_addr.IsValid()) { 458554f68d3SGreg Clayton const char *addr_offset_padding = no_padding ? "" : " "; 459554f68d3SGreg Clayton 460b9c1b51eSKate Stone if (func_addr.GetSection() == format_addr.GetSection()) { 461554f68d3SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 462554f68d3SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 463b9c1b51eSKate Stone if (addr_file_addr > func_file_addr || 464b9c1b51eSKate Stone (addr_file_addr == func_file_addr && print_zero_offsets)) { 465b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 466b9c1b51eSKate Stone addr_file_addr - func_file_addr); 467b9c1b51eSKate Stone } else if (addr_file_addr < func_file_addr) { 468b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 469b9c1b51eSKate Stone func_file_addr - addr_file_addr); 470c980fa92SJason Molenda } 471554f68d3SGreg Clayton return true; 472b9c1b51eSKate Stone } else { 473554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 474b9c1b51eSKate Stone if (target) { 475554f68d3SGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress(target); 476554f68d3SGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress(target); 477b9c1b51eSKate Stone if (addr_load_addr > func_load_addr || 478b9c1b51eSKate Stone (addr_load_addr == func_load_addr && print_zero_offsets)) { 479b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 480b9c1b51eSKate Stone addr_load_addr - func_load_addr); 481b9c1b51eSKate Stone } else if (addr_load_addr < func_load_addr) { 482b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 483b9c1b51eSKate Stone func_load_addr - addr_load_addr); 484c980fa92SJason Molenda } 485554f68d3SGreg Clayton return true; 486554f68d3SGreg Clayton } 487554f68d3SGreg Clayton } 488554f68d3SGreg Clayton } 489554f68d3SGreg Clayton } 490554f68d3SGreg Clayton return false; 491554f68d3SGreg Clayton } 492554f68d3SGreg Clayton 493b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath, 494554f68d3SGreg Clayton size_t &close_bracket_index, 495554f68d3SGreg Clayton const char *&var_name_final_if_array_range, 496b9c1b51eSKate Stone int64_t &index_lower, int64_t &index_higher) { 4974edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 498554f68d3SGreg Clayton close_bracket_index = llvm::StringRef::npos; 499554f68d3SGreg Clayton const size_t open_bracket_index = subpath.find('['); 500b9c1b51eSKate Stone if (open_bracket_index == llvm::StringRef::npos) { 501554f68d3SGreg Clayton if (log) 502554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 503554f68d3SGreg Clayton return false; 504554f68d3SGreg Clayton } 505554f68d3SGreg Clayton 506554f68d3SGreg Clayton close_bracket_index = subpath.find(']', open_bracket_index + 1); 507554f68d3SGreg Clayton 508b9c1b51eSKate Stone if (close_bracket_index == llvm::StringRef::npos) { 509554f68d3SGreg Clayton if (log) 510554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 511554f68d3SGreg Clayton return false; 512b9c1b51eSKate Stone } else { 513554f68d3SGreg Clayton var_name_final_if_array_range = subpath.data() + open_bracket_index; 514554f68d3SGreg Clayton 515b9c1b51eSKate Stone if (close_bracket_index - open_bracket_index == 1) { 516554f68d3SGreg Clayton if (log) 517b9c1b51eSKate Stone log->Printf( 518b9c1b51eSKate Stone "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 519554f68d3SGreg Clayton index_lower = 0; 520b9c1b51eSKate Stone } else { 521554f68d3SGreg Clayton const size_t separator_index = subpath.find('-', open_bracket_index + 1); 522554f68d3SGreg Clayton 523b9c1b51eSKate Stone if (separator_index == llvm::StringRef::npos) { 524554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 525a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 526554f68d3SGreg Clayton index_higher = index_lower; 527554f68d3SGreg Clayton if (log) 528b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 529b9c1b51eSKate Stone "] detected, high index is same", 530b9c1b51eSKate Stone index_lower); 531b9c1b51eSKate Stone } else { 532554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 533554f68d3SGreg Clayton const char *index_higher_cstr = subpath.data() + separator_index + 1; 534a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 535a74f37a5SEugene Zelenko index_higher = ::strtoul(index_higher_cstr, nullptr, 0); 536554f68d3SGreg Clayton if (log) 537b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", 538b9c1b51eSKate Stone index_lower, index_higher); 539554f68d3SGreg Clayton } 540b9c1b51eSKate Stone if (index_lower > index_higher && index_higher > 0) { 541554f68d3SGreg Clayton if (log) 542554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] swapping indices"); 543554f68d3SGreg Clayton const int64_t temp = index_lower; 544554f68d3SGreg Clayton index_lower = index_higher; 545554f68d3SGreg Clayton index_higher = temp; 546554f68d3SGreg Clayton } 547554f68d3SGreg Clayton } 548554f68d3SGreg Clayton } 549554f68d3SGreg Clayton return true; 550554f68d3SGreg Clayton } 551554f68d3SGreg Clayton 552b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { 553b9c1b51eSKate Stone switch (file_kind) { 554554f68d3SGreg Clayton case FileKind::FileError: 555554f68d3SGreg Clayton break; 556554f68d3SGreg Clayton 557554f68d3SGreg Clayton case FileKind::Basename: 558b9c1b51eSKate Stone if (file.GetFilename()) { 559554f68d3SGreg Clayton s << file.GetFilename(); 560554f68d3SGreg Clayton return true; 561554f68d3SGreg Clayton } 562554f68d3SGreg Clayton break; 563554f68d3SGreg Clayton 564554f68d3SGreg Clayton case FileKind::Dirname: 565b9c1b51eSKate Stone if (file.GetDirectory()) { 566554f68d3SGreg Clayton s << file.GetDirectory(); 567554f68d3SGreg Clayton return true; 568554f68d3SGreg Clayton } 569554f68d3SGreg Clayton break; 570554f68d3SGreg Clayton 571554f68d3SGreg Clayton case FileKind::Fullpath: 572b9c1b51eSKate Stone if (file) { 573554f68d3SGreg Clayton s << file; 574554f68d3SGreg Clayton return true; 575554f68d3SGreg Clayton } 576554f68d3SGreg Clayton break; 577554f68d3SGreg Clayton } 578554f68d3SGreg Clayton return false; 579554f68d3SGreg Clayton } 580554f68d3SGreg Clayton 581b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, 582b9c1b51eSKate Stone uint32_t reg_num, Format format) 583554f68d3SGreg Clayton 584554f68d3SGreg Clayton { 585b9c1b51eSKate Stone if (frame) { 586554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 587554f68d3SGreg Clayton 588b9c1b51eSKate Stone if (reg_ctx) { 589b9c1b51eSKate Stone const uint32_t lldb_reg_num = 590b9c1b51eSKate Stone reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 591b9c1b51eSKate Stone if (lldb_reg_num != LLDB_INVALID_REGNUM) { 592b9c1b51eSKate Stone const RegisterInfo *reg_info = 593b9c1b51eSKate Stone reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); 594b9c1b51eSKate Stone if (reg_info) { 595554f68d3SGreg Clayton RegisterValue reg_value; 596b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 597554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 598554f68d3SGreg Clayton return true; 599554f68d3SGreg Clayton } 600554f68d3SGreg Clayton } 601554f68d3SGreg Clayton } 602554f68d3SGreg Clayton } 603554f68d3SGreg Clayton } 604554f68d3SGreg Clayton return false; 605554f68d3SGreg Clayton } 606554f68d3SGreg Clayton 607b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, 608554f68d3SGreg Clayton StackFrame *frame, 609b9c1b51eSKate Stone bool deref_pointer) { 6104edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 611554f68d3SGreg Clayton const char *ptr_deref_format = "[%d]"; 612554f68d3SGreg Clayton std::string ptr_deref_buffer(10, 0); 613554f68d3SGreg Clayton ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 614554f68d3SGreg Clayton if (log) 615b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] name to deref: %s", 616b9c1b51eSKate Stone ptr_deref_buffer.c_str()); 617554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 618554f68d3SGreg Clayton ValueObject::ExpressionPathEndResultType final_value_type; 619554f68d3SGreg Clayton ValueObject::ExpressionPathScanEndReason reason_to_stop; 620b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 621b9c1b51eSKate Stone (deref_pointer ? ValueObject::eExpressionPathAftermathDereference 622b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 623b9c1b51eSKate Stone ValueObjectSP item = valobj->GetValueForExpressionPath( 624d2daca77SZachary Turner ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, 625d2daca77SZachary Turner &what_next); 626b9c1b51eSKate Stone if (!item) { 627554f68d3SGreg Clayton if (log) 628d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d," 629554f68d3SGreg Clayton " final_value_type %d", 630d2daca77SZachary Turner reason_to_stop, final_value_type); 631b9c1b51eSKate Stone } else { 632554f68d3SGreg Clayton if (log) 633d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," 634554f68d3SGreg Clayton " final_value_type %d", 635d2daca77SZachary Turner reason_to_stop, final_value_type); 636554f68d3SGreg Clayton } 637554f68d3SGreg Clayton return item; 638554f68d3SGreg Clayton } 639554f68d3SGreg Clayton 640b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar( 641b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle style) { 642b9c1b51eSKate Stone switch (style) { 643b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: 644b9c1b51eSKate Stone return '@'; 645b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleValue: 646b9c1b51eSKate Stone return 'V'; 647b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLocation: 648b9c1b51eSKate Stone return 'L'; 649b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleSummary: 650b9c1b51eSKate Stone return 'S'; 651b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleChildrenCount: 652b9c1b51eSKate Stone return '#'; 653b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleType: 654b9c1b51eSKate Stone return 'T'; 655b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleName: 656b9c1b51eSKate Stone return 'N'; 657b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleExpressionPath: 658b9c1b51eSKate Stone return '>'; 659554f68d3SGreg Clayton } 660554f68d3SGreg Clayton return '\0'; 661554f68d3SGreg Clayton } 662554f68d3SGreg Clayton 663b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc, 664554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 665b9c1b51eSKate Stone const FormatEntity::Entry &entry, ValueObject *valobj) { 666a74f37a5SEugene Zelenko if (valobj == nullptr) 667554f68d3SGreg Clayton return false; 668554f68d3SGreg Clayton 6694edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 670554f68d3SGreg Clayton Format custom_format = eFormatInvalid; 671b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle val_obj_display = 672b9c1b51eSKate Stone entry.string.empty() 673b9c1b51eSKate Stone ? ValueObject::eValueObjectRepresentationStyleValue 674b9c1b51eSKate Stone : ValueObject::eValueObjectRepresentationStyleSummary; 675554f68d3SGreg Clayton 676554f68d3SGreg Clayton bool do_deref_pointer = entry.deref; 677554f68d3SGreg Clayton bool is_script = false; 678b9c1b51eSKate Stone switch (entry.type) { 679554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariable: 680554f68d3SGreg Clayton is_script = true; 681554f68d3SGreg Clayton break; 682554f68d3SGreg Clayton 683554f68d3SGreg Clayton case FormatEntity::Entry::Type::Variable: 684554f68d3SGreg Clayton custom_format = entry.fmt; 685554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 686554f68d3SGreg Clayton break; 687554f68d3SGreg Clayton 688554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariableSynthetic: 689554f68d3SGreg Clayton is_script = true; 69062e0681aSJason Molenda LLVM_FALLTHROUGH; 691554f68d3SGreg Clayton case FormatEntity::Entry::Type::VariableSynthetic: 692554f68d3SGreg Clayton custom_format = entry.fmt; 693554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 694b9c1b51eSKate Stone if (!valobj->IsSynthetic()) { 695554f68d3SGreg Clayton valobj = valobj->GetSyntheticValue().get(); 696554f68d3SGreg Clayton if (valobj == nullptr) 697554f68d3SGreg Clayton return false; 698554f68d3SGreg Clayton } 699554f68d3SGreg Clayton break; 700554f68d3SGreg Clayton 701554f68d3SGreg Clayton default: 702554f68d3SGreg Clayton return false; 703554f68d3SGreg Clayton } 704554f68d3SGreg Clayton 705a74f37a5SEugene Zelenko if (valobj == nullptr) 706554f68d3SGreg Clayton return false; 707554f68d3SGreg Clayton 708b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 709b9c1b51eSKate Stone (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference 710b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 711554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 712b9c1b51eSKate Stone options.DontCheckDotVsArrowSyntax() 713b9c1b51eSKate Stone .DoAllowBitfieldSyntax() 714b9c1b51eSKate Stone .DoAllowFragileIVar() 715b9c1b51eSKate Stone .SetSyntheticChildrenTraversal( 716b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions:: 717b9c1b51eSKate Stone SyntheticChildrenTraversal::Both); 718a74f37a5SEugene Zelenko ValueObject *target = nullptr; 719a74f37a5SEugene Zelenko const char *var_name_final_if_array_range = nullptr; 720554f68d3SGreg Clayton size_t close_bracket_index = llvm::StringRef::npos; 721554f68d3SGreg Clayton int64_t index_lower = -1; 722554f68d3SGreg Clayton int64_t index_higher = -1; 723554f68d3SGreg Clayton bool is_array_range = false; 724554f68d3SGreg Clayton bool was_plain_var = false; 725554f68d3SGreg Clayton bool was_var_format = false; 726554f68d3SGreg Clayton bool was_var_indexed = false; 727b9c1b51eSKate Stone ValueObject::ExpressionPathScanEndReason reason_to_stop = 728b9c1b51eSKate Stone ValueObject::eExpressionPathScanEndReasonEndOfString; 729b9c1b51eSKate Stone ValueObject::ExpressionPathEndResultType final_value_type = 730b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypePlain; 731554f68d3SGreg Clayton 732b9c1b51eSKate Stone if (is_script) { 733554f68d3SGreg Clayton return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); 734554f68d3SGreg Clayton } 735554f68d3SGreg Clayton 736554f68d3SGreg Clayton llvm::StringRef subpath(entry.string); 737554f68d3SGreg Clayton // simplest case ${var}, just print valobj's value 738b9c1b51eSKate Stone if (entry.string.empty()) { 739b9c1b51eSKate Stone if (entry.printf_format.empty() && entry.fmt == eFormatDefault && 740b9c1b51eSKate Stone entry.number == ValueObject::eValueObjectRepresentationStyleValue) 741554f68d3SGreg Clayton was_plain_var = true; 742554f68d3SGreg Clayton else 743554f68d3SGreg Clayton was_var_format = true; 744554f68d3SGreg Clayton target = valobj; 745b9c1b51eSKate Stone } else // this is ${var.something} or multiple .something nested 746554f68d3SGreg Clayton { 747554f68d3SGreg Clayton if (entry.string[0] == '[') 748554f68d3SGreg Clayton was_var_indexed = true; 749b9c1b51eSKate Stone ScanBracketedRange(subpath, close_bracket_index, 750b9c1b51eSKate Stone var_name_final_if_array_range, index_lower, 751554f68d3SGreg Clayton index_higher); 752554f68d3SGreg Clayton 753554f68d3SGreg Clayton Error error; 754554f68d3SGreg Clayton 755554f68d3SGreg Clayton const std::string &expr_path = entry.string; 756554f68d3SGreg Clayton 757554f68d3SGreg Clayton if (log) 758b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", 759b9c1b51eSKate Stone expr_path.c_str()); 760554f68d3SGreg Clayton 761d2daca77SZachary Turner target = 762d2daca77SZachary Turner valobj 763d2daca77SZachary Turner ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, 764d2daca77SZachary Turner &final_value_type, options, &what_next) 765b9c1b51eSKate Stone .get(); 766554f68d3SGreg Clayton 767b9c1b51eSKate Stone if (!target) { 768554f68d3SGreg Clayton if (log) 769d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d," 770655c4525SZachary Turner " final_value_type %d", 771d2daca77SZachary Turner reason_to_stop, final_value_type); 772554f68d3SGreg Clayton return false; 773b9c1b51eSKate Stone } else { 774554f68d3SGreg Clayton if (log) 775d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," 776655c4525SZachary Turner " final_value_type %d", 777d2daca77SZachary Turner reason_to_stop, final_value_type); 778b9c1b51eSKate Stone target = target 779b9c1b51eSKate Stone ->GetQualifiedRepresentationIfAvailable( 780b9c1b51eSKate Stone target->GetDynamicValueType(), true) 781b9c1b51eSKate Stone .get(); 782554f68d3SGreg Clayton } 783554f68d3SGreg Clayton } 784554f68d3SGreg Clayton 785b9c1b51eSKate Stone is_array_range = 786b9c1b51eSKate Stone (final_value_type == 787b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeBoundedRange || 788b9c1b51eSKate Stone final_value_type == 789b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeUnboundedRange); 790554f68d3SGreg Clayton 791b9c1b51eSKate Stone do_deref_pointer = 792b9c1b51eSKate Stone (what_next == ValueObject::eExpressionPathAftermathDereference); 793554f68d3SGreg Clayton 794b9c1b51eSKate Stone if (do_deref_pointer && !is_array_range) { 795554f68d3SGreg Clayton // I have not deref-ed yet, let's do it 796b9c1b51eSKate Stone // this happens when we are not going through 797b9c1b51eSKate Stone // GetValueForVariableExpressionPath 798554f68d3SGreg Clayton // to get to the target ValueObject 799554f68d3SGreg Clayton Error error; 800554f68d3SGreg Clayton target = target->Dereference(error).get(); 801b9c1b51eSKate Stone if (error.Fail()) { 802554f68d3SGreg Clayton if (log) 803b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", 804b9c1b51eSKate Stone error.AsCString("unknown")); 805554f68d3SGreg Clayton return false; 806554f68d3SGreg Clayton } 807554f68d3SGreg Clayton do_deref_pointer = false; 808554f68d3SGreg Clayton } 809554f68d3SGreg Clayton 810b9c1b51eSKate Stone if (!target) { 811554f68d3SGreg Clayton if (log) 812b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] could not calculate target for " 813b9c1b51eSKate Stone "prompt expression"); 814554f68d3SGreg Clayton return false; 815554f68d3SGreg Clayton } 816554f68d3SGreg Clayton 817554f68d3SGreg Clayton // we do not want to use the summary for a bitfield of type T:n 818554f68d3SGreg Clayton // if we were originally dealing with just a T - that would get 819554f68d3SGreg Clayton // us into an endless recursion 820b9c1b51eSKate Stone if (target->IsBitfield() && was_var_indexed) { 821554f68d3SGreg Clayton // TODO: check for a (T:n)-specific summary - we should still obey that 822554f68d3SGreg Clayton StreamString bitfield_name; 823b9c1b51eSKate Stone bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), 824b9c1b51eSKate Stone target->GetBitfieldBitSize()); 825b9c1b51eSKate Stone lldb::TypeNameSpecifierImplSP type_sp( 826c156427dSZachary Turner new TypeNameSpecifierImpl(bitfield_name.GetString(), false)); 827b9c1b51eSKate Stone if (val_obj_display == 828b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary && 829b9c1b51eSKate Stone !DataVisualization::GetSummaryForType(type_sp)) 830554f68d3SGreg Clayton val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 831554f68d3SGreg Clayton } 832554f68d3SGreg Clayton 833554f68d3SGreg Clayton // TODO use flags for these 834b9c1b51eSKate Stone const uint32_t type_info_flags = 835b9c1b51eSKate Stone target->GetCompilerType().GetTypeInfo(nullptr); 836554f68d3SGreg Clayton bool is_array = (type_info_flags & eTypeIsArray) != 0; 837554f68d3SGreg Clayton bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 83899558cc4SGreg Clayton bool is_aggregate = target->GetCompilerType().IsAggregateType(); 839554f68d3SGreg Clayton 840b9c1b51eSKate Stone if ((is_array || is_pointer) && (!is_array_range) && 841b9c1b51eSKate Stone val_obj_display == 842b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue) // this should be 843b9c1b51eSKate Stone // wrong, but there 844b9c1b51eSKate Stone // are some 845b9c1b51eSKate Stone // exceptions 846554f68d3SGreg Clayton { 847554f68d3SGreg Clayton StreamString str_temp; 848554f68d3SGreg Clayton if (log) 849b9c1b51eSKate Stone log->Printf( 850b9c1b51eSKate Stone "[Debugger::FormatPrompt] I am into array || pointer && !range"); 851554f68d3SGreg Clayton 852b9c1b51eSKate Stone if (target->HasSpecialPrintableRepresentation(val_obj_display, 853b9c1b51eSKate Stone custom_format)) { 854554f68d3SGreg Clayton // try to use the special cases 855b9c1b51eSKate Stone bool success = target->DumpPrintableRepresentation( 856b9c1b51eSKate Stone str_temp, val_obj_display, custom_format); 857554f68d3SGreg Clayton if (log) 858b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] special cases did%s match", 859b9c1b51eSKate Stone success ? "" : "n't"); 860554f68d3SGreg Clayton 861554f68d3SGreg Clayton // should not happen 862554f68d3SGreg Clayton if (success) 863c156427dSZachary Turner s << str_temp.GetString(); 864554f68d3SGreg Clayton return true; 865b9c1b51eSKate Stone } else { 866554f68d3SGreg Clayton if (was_plain_var) // if ${var} 867554f68d3SGreg Clayton { 868554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 869b9c1b51eSKate Stone } else if (is_pointer) // if pointer, value is the address stored 870554f68d3SGreg Clayton { 871b9c1b51eSKate Stone target->DumpPrintableRepresentation( 872b9c1b51eSKate Stone s, val_obj_display, custom_format, 87365d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable); 874554f68d3SGreg Clayton } 875554f68d3SGreg Clayton return true; 876554f68d3SGreg Clayton } 877554f68d3SGreg Clayton } 878554f68d3SGreg Clayton 879b9c1b51eSKate Stone // if directly trying to print ${var}, and this is an aggregate, display a 880b9c1b51eSKate Stone // nice 881554f68d3SGreg Clayton // type @ location message 882b9c1b51eSKate Stone if (is_aggregate && was_plain_var) { 883554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 884554f68d3SGreg Clayton return true; 885554f68d3SGreg Clayton } 886554f68d3SGreg Clayton 887b9c1b51eSKate Stone // if directly trying to print ${var%V}, and this is an aggregate, do not let 888b9c1b51eSKate Stone // the user do it 889b9c1b51eSKate Stone if (is_aggregate && 890b9c1b51eSKate Stone ((was_var_format && 891b9c1b51eSKate Stone val_obj_display == 892b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue))) { 893554f68d3SGreg Clayton s << "<invalid use of aggregate type>"; 894554f68d3SGreg Clayton return true; 895554f68d3SGreg Clayton } 896554f68d3SGreg Clayton 897b9c1b51eSKate Stone if (!is_array_range) { 898554f68d3SGreg Clayton if (log) 899554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 900b9c1b51eSKate Stone return target->DumpPrintableRepresentation(s, val_obj_display, 901b9c1b51eSKate Stone custom_format); 902b9c1b51eSKate Stone } else { 903554f68d3SGreg Clayton if (log) 904554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 905554f68d3SGreg Clayton if (!is_array && !is_pointer) 906554f68d3SGreg Clayton return false; 907554f68d3SGreg Clayton if (log) 908554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] handle as array"); 909e8376261SVince Harron StreamString special_directions_stream; 910554f68d3SGreg Clayton llvm::StringRef special_directions; 911b9c1b51eSKate Stone if (close_bracket_index != llvm::StringRef::npos && 912b9c1b51eSKate Stone subpath.size() > close_bracket_index) { 913554f68d3SGreg Clayton ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); 914b9c1b51eSKate Stone special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", 915554f68d3SGreg Clayton additional_data.GetCString()); 916554f68d3SGreg Clayton 917b9c1b51eSKate Stone if (entry.fmt != eFormatDefault) { 918b9c1b51eSKate Stone const char format_char = 919b9c1b51eSKate Stone FormatManager::GetFormatAsFormatChar(entry.fmt); 920554f68d3SGreg Clayton if (format_char != '\0') 921554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", format_char); 922b9c1b51eSKate Stone else { 923b9c1b51eSKate Stone const char *format_cstr = 924b9c1b51eSKate Stone FormatManager::GetFormatAsCString(entry.fmt); 925554f68d3SGreg Clayton special_directions_stream.Printf("%%%s", format_cstr); 926554f68d3SGreg Clayton } 927b9c1b51eSKate Stone } else if (entry.number != 0) { 928b9c1b51eSKate Stone const char style_char = ConvertValueObjectStyleToChar( 929b9c1b51eSKate Stone (ValueObject::ValueObjectRepresentationStyle)entry.number); 930554f68d3SGreg Clayton if (style_char) 931554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", style_char); 932554f68d3SGreg Clayton } 933554f68d3SGreg Clayton special_directions_stream.PutChar('}'); 934b9c1b51eSKate Stone special_directions = 935b9c1b51eSKate Stone llvm::StringRef(special_directions_stream.GetString()); 936554f68d3SGreg Clayton } 937554f68d3SGreg Clayton 938554f68d3SGreg Clayton // let us display items index_lower thru index_higher of this array 939554f68d3SGreg Clayton s.PutChar('['); 940554f68d3SGreg Clayton 941554f68d3SGreg Clayton if (index_higher < 0) 942554f68d3SGreg Clayton index_higher = valobj->GetNumChildren() - 1; 943554f68d3SGreg Clayton 944b9c1b51eSKate Stone uint32_t max_num_children = 945b9c1b51eSKate Stone target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 946554f68d3SGreg Clayton 947554f68d3SGreg Clayton bool success = true; 948b9c1b51eSKate Stone for (int64_t index = index_lower; index <= index_higher; ++index) { 949b9c1b51eSKate Stone ValueObject *item = 950b9c1b51eSKate Stone ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) 951b9c1b51eSKate Stone .get(); 952554f68d3SGreg Clayton 953b9c1b51eSKate Stone if (!item) { 954554f68d3SGreg Clayton if (log) 955b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " 956b9c1b51eSKate Stone "index %" PRId64, 957b9c1b51eSKate Stone index); 958b9c1b51eSKate Stone } else { 959554f68d3SGreg Clayton if (log) 960b9c1b51eSKate Stone log->Printf( 961b9c1b51eSKate Stone "[Debugger::FormatPrompt] special_directions for child item: %s", 962b9c1b51eSKate Stone special_directions.data() ? special_directions.data() : ""); 963554f68d3SGreg Clayton } 964554f68d3SGreg Clayton 965b9c1b51eSKate Stone if (special_directions.empty()) { 966b9c1b51eSKate Stone success &= item->DumpPrintableRepresentation(s, val_obj_display, 967b9c1b51eSKate Stone custom_format); 968b9c1b51eSKate Stone } else { 969b9c1b51eSKate Stone success &= FormatEntity::FormatStringRef( 970b9c1b51eSKate Stone special_directions, s, sc, exe_ctx, nullptr, item, false, false); 971554f68d3SGreg Clayton } 972554f68d3SGreg Clayton 973b9c1b51eSKate Stone if (--max_num_children == 0) { 974554f68d3SGreg Clayton s.PutCString(", ..."); 975554f68d3SGreg Clayton break; 976554f68d3SGreg Clayton } 977554f68d3SGreg Clayton 978554f68d3SGreg Clayton if (index < index_higher) 979554f68d3SGreg Clayton s.PutChar(','); 980554f68d3SGreg Clayton } 981554f68d3SGreg Clayton s.PutChar(']'); 982554f68d3SGreg Clayton return success; 983554f68d3SGreg Clayton } 984554f68d3SGreg Clayton } 985554f68d3SGreg Clayton 986b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, 987b9c1b51eSKate Stone Format format) { 988b9c1b51eSKate Stone if (frame) { 989554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 990554f68d3SGreg Clayton 991b9c1b51eSKate Stone if (reg_ctx) { 992554f68d3SGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 993b9c1b51eSKate Stone if (reg_info) { 994554f68d3SGreg Clayton RegisterValue reg_value; 995b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 996554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 997554f68d3SGreg Clayton return true; 998554f68d3SGreg Clayton } 999554f68d3SGreg Clayton } 1000554f68d3SGreg Clayton } 1001554f68d3SGreg Clayton } 1002554f68d3SGreg Clayton return false; 1003554f68d3SGreg Clayton } 1004554f68d3SGreg Clayton 1005b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse( 1006b9c1b51eSKate Stone const FormatEntity::Entry &entry, 1007554f68d3SGreg Clayton const StructuredData::ObjectSP &thread_info_dictionary, 1008b9c1b51eSKate Stone const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { 1009554f68d3SGreg Clayton llvm::StringRef path(entry.string); 1010554f68d3SGreg Clayton 1011b9c1b51eSKate Stone StructuredData::ObjectSP value = 1012b9c1b51eSKate Stone thread_info_dictionary->GetObjectForDotSeparatedPath(path); 1013554f68d3SGreg Clayton 1014b9c1b51eSKate Stone if (value) { 1015b9c1b51eSKate Stone if (value->GetType() == StructuredData::Type::eTypeInteger) { 1016554f68d3SGreg Clayton const char *token_format = "0x%4.4" PRIx64; 1017554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1018554f68d3SGreg Clayton token_format = entry.printf_format.c_str(); 1019554f68d3SGreg Clayton s.Printf(token_format, value->GetAsInteger()->GetValue()); 1020554f68d3SGreg Clayton return true; 1021b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeFloat) { 1022554f68d3SGreg Clayton s.Printf("%f", value->GetAsFloat()->GetValue()); 1023554f68d3SGreg Clayton return true; 1024b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeString) { 1025554f68d3SGreg Clayton s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1026554f68d3SGreg Clayton return true; 1027b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeArray) { 1028b9c1b51eSKate Stone if (value->GetAsArray()->GetSize() > 0) { 1029554f68d3SGreg Clayton s.Printf("%zu", value->GetAsArray()->GetSize()); 1030554f68d3SGreg Clayton return true; 1031554f68d3SGreg Clayton } 1032b9c1b51eSKate Stone } else if (value->GetType() == StructuredData::Type::eTypeDictionary) { 1033b9c1b51eSKate Stone s.Printf("%zu", 1034b9c1b51eSKate Stone value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1035554f68d3SGreg Clayton return true; 1036554f68d3SGreg Clayton } 1037554f68d3SGreg Clayton } 1038554f68d3SGreg Clayton 1039554f68d3SGreg Clayton return false; 1040554f68d3SGreg Clayton } 1041554f68d3SGreg Clayton 1042b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) { 1043554f68d3SGreg Clayton return (::strncmp(var_name_begin, var, strlen(var)) == 0); 1044554f68d3SGreg Clayton } 1045554f68d3SGreg Clayton 1046b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, 1047554f68d3SGreg Clayton const SymbolContext *sc, 1048554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1049b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1050554f68d3SGreg Clayton bool function_changed, 1051b9c1b51eSKate Stone bool initial_function) { 1052b9c1b51eSKate Stone if (!format_str.empty()) { 1053554f68d3SGreg Clayton FormatEntity::Entry root; 1054554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1055b9c1b51eSKate Stone if (error.Success()) { 1056b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1057b9c1b51eSKate Stone function_changed, initial_function); 1058554f68d3SGreg Clayton } 1059554f68d3SGreg Clayton } 1060554f68d3SGreg Clayton return false; 1061554f68d3SGreg Clayton } 1062a74f37a5SEugene Zelenko 1063b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s, 1064554f68d3SGreg Clayton const SymbolContext *sc, 1065554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1066b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1067b9c1b51eSKate Stone bool function_changed, bool initial_function) { 1068b9c1b51eSKate Stone if (format && format[0]) { 1069554f68d3SGreg Clayton FormatEntity::Entry root; 1070554f68d3SGreg Clayton llvm::StringRef format_str(format); 1071554f68d3SGreg Clayton Error error = FormatEntity::Parse(format_str, root); 1072b9c1b51eSKate Stone if (error.Success()) { 1073b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1074b9c1b51eSKate Stone function_changed, initial_function); 1075554f68d3SGreg Clayton } 1076554f68d3SGreg Clayton } 1077554f68d3SGreg Clayton return false; 1078554f68d3SGreg Clayton } 1079554f68d3SGreg Clayton 1080b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s, 1081554f68d3SGreg Clayton const SymbolContext *sc, 1082b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address *addr, 1083b9c1b51eSKate Stone ValueObject *valobj, bool function_changed, 1084b9c1b51eSKate Stone bool initial_function) { 1085b9c1b51eSKate Stone switch (entry.type) { 1086554f68d3SGreg Clayton case Entry::Type::Invalid: 1087b9c1b51eSKate Stone case Entry::Type::ParentNumber: // Only used for 1088b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1089b9c1b51eSKate Stone case Entry::Type::ParentString: // Only used for 1090b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1091b9c1b51eSKate Stone case Entry::Type::InsertString: // Only used for 1092b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1093554f68d3SGreg Clayton return false; 1094554f68d3SGreg Clayton 1095554f68d3SGreg Clayton case Entry::Type::Root: 1096b9c1b51eSKate Stone for (const auto &child : entry.children) { 1097b9c1b51eSKate Stone if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, 1098b9c1b51eSKate Stone initial_function)) { 1099554f68d3SGreg Clayton return false; // If any item of root fails, then the formatting fails 1100554f68d3SGreg Clayton } 1101554f68d3SGreg Clayton } 1102554f68d3SGreg Clayton return true; // Only return true if all items succeeded 1103554f68d3SGreg Clayton 1104554f68d3SGreg Clayton case Entry::Type::String: 1105771ef6d4SMalcolm Parsons s.PutCString(entry.string); 1106554f68d3SGreg Clayton return true; 1107554f68d3SGreg Clayton 1108b9c1b51eSKate Stone case Entry::Type::Scope: { 1109554f68d3SGreg Clayton StreamString scope_stream; 1110554f68d3SGreg Clayton bool success = false; 1111b9c1b51eSKate Stone for (const auto &child : entry.children) { 1112b9c1b51eSKate Stone success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, 1113b9c1b51eSKate Stone function_changed, initial_function); 1114554f68d3SGreg Clayton if (!success) 1115554f68d3SGreg Clayton break; 1116554f68d3SGreg Clayton } 1117554f68d3SGreg Clayton // Only if all items in a scope succeed, then do we 1118554f68d3SGreg Clayton // print the output into the main stream 1119554f68d3SGreg Clayton if (success) 1120554f68d3SGreg Clayton s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1121554f68d3SGreg Clayton } 1122554f68d3SGreg Clayton return true; // Scopes always successfully print themselves 1123554f68d3SGreg Clayton 1124554f68d3SGreg Clayton case Entry::Type::Variable: 1125554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 1126554f68d3SGreg Clayton case Entry::Type::ScriptVariable: 1127554f68d3SGreg Clayton case Entry::Type::ScriptVariableSynthetic: 1128a74f37a5SEugene Zelenko return DumpValue(s, sc, exe_ctx, entry, valobj); 1129554f68d3SGreg Clayton 1130554f68d3SGreg Clayton case Entry::Type::AddressFile: 1131554f68d3SGreg Clayton case Entry::Type::AddressLoad: 1132554f68d3SGreg Clayton case Entry::Type::AddressLoadOrFile: 1133a74f37a5SEugene Zelenko return (addr != nullptr && addr->IsValid() && 1134b9c1b51eSKate Stone DumpAddress(s, sc, exe_ctx, *addr, 1135b9c1b51eSKate Stone entry.type == Entry::Type::AddressLoadOrFile)); 1136554f68d3SGreg Clayton 1137554f68d3SGreg Clayton case Entry::Type::ProcessID: 1138b9c1b51eSKate Stone if (exe_ctx) { 1139554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1140b9c1b51eSKate Stone if (process) { 1141554f68d3SGreg Clayton const char *format = "%" PRIu64; 1142554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1143554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1144554f68d3SGreg Clayton s.Printf(format, process->GetID()); 1145554f68d3SGreg Clayton return true; 1146554f68d3SGreg Clayton } 1147554f68d3SGreg Clayton } 1148554f68d3SGreg Clayton return false; 1149554f68d3SGreg Clayton 1150554f68d3SGreg Clayton case Entry::Type::ProcessFile: 1151b9c1b51eSKate Stone if (exe_ctx) { 1152554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1153b9c1b51eSKate Stone if (process) { 1154554f68d3SGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1155b9c1b51eSKate Stone if (exe_module) { 1156554f68d3SGreg Clayton if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1157554f68d3SGreg Clayton return true; 1158554f68d3SGreg Clayton } 1159554f68d3SGreg Clayton } 1160554f68d3SGreg Clayton } 1161554f68d3SGreg Clayton return false; 1162554f68d3SGreg Clayton 1163554f68d3SGreg Clayton case Entry::Type::ScriptProcess: 1164b9c1b51eSKate Stone if (exe_ctx) { 1165554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1166554f68d3SGreg Clayton if (process) 1167b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, process, 1168b9c1b51eSKate Stone entry.string.c_str()); 1169554f68d3SGreg Clayton } 1170554f68d3SGreg Clayton return false; 1171554f68d3SGreg Clayton 1172554f68d3SGreg Clayton case Entry::Type::ThreadID: 1173b9c1b51eSKate Stone if (exe_ctx) { 1174554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1175b9c1b51eSKate Stone if (thread) { 1176554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1177b9c1b51eSKate Stone if (!entry.printf_format.empty()) { 1178554f68d3SGreg Clayton // Watch for the special "tid" format... 1179b9c1b51eSKate Stone if (entry.printf_format == "tid") { 1180b9c1b51eSKate Stone // TODO(zturner): Rather than hardcoding this to be platform 1181b9c1b51eSKate Stone // specific, it should be controlled by a 1182b9c1b51eSKate Stone // setting and the default value of the setting can be different 1183b9c1b51eSKate Stone // depending on the platform. 1184554f68d3SGreg Clayton Target &target = thread->GetProcess()->GetTarget(); 1185554f68d3SGreg Clayton ArchSpec arch(target.GetArchitecture()); 1186b9c1b51eSKate Stone llvm::Triple::OSType ostype = arch.IsValid() 1187b9c1b51eSKate Stone ? arch.GetTriple().getOS() 1188b9c1b51eSKate Stone : llvm::Triple::UnknownOS; 1189b9c1b51eSKate Stone if ((ostype == llvm::Triple::FreeBSD) || 1190b9c1b51eSKate Stone (ostype == llvm::Triple::Linux)) { 1191554f68d3SGreg Clayton format = "%" PRIu64; 1192554f68d3SGreg Clayton } 1193b9c1b51eSKate Stone } else { 1194554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1195554f68d3SGreg Clayton } 1196554f68d3SGreg Clayton } 1197554f68d3SGreg Clayton s.Printf(format, thread->GetID()); 1198554f68d3SGreg Clayton return true; 1199554f68d3SGreg Clayton } 1200554f68d3SGreg Clayton } 1201554f68d3SGreg Clayton return false; 1202554f68d3SGreg Clayton 1203554f68d3SGreg Clayton case Entry::Type::ThreadProtocolID: 1204b9c1b51eSKate Stone if (exe_ctx) { 1205554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1206b9c1b51eSKate Stone if (thread) { 1207554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1208554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1209554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1210554f68d3SGreg Clayton s.Printf(format, thread->GetProtocolID()); 1211554f68d3SGreg Clayton return true; 1212554f68d3SGreg Clayton } 1213554f68d3SGreg Clayton } 1214554f68d3SGreg Clayton return false; 1215554f68d3SGreg Clayton 1216554f68d3SGreg Clayton case Entry::Type::ThreadIndexID: 1217b9c1b51eSKate Stone if (exe_ctx) { 1218554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1219b9c1b51eSKate Stone if (thread) { 1220554f68d3SGreg Clayton const char *format = "%" PRIu32; 1221554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1222554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1223554f68d3SGreg Clayton s.Printf(format, thread->GetIndexID()); 1224554f68d3SGreg Clayton return true; 1225554f68d3SGreg Clayton } 1226554f68d3SGreg Clayton } 1227554f68d3SGreg Clayton return false; 1228554f68d3SGreg Clayton 1229554f68d3SGreg Clayton case Entry::Type::ThreadName: 1230b9c1b51eSKate Stone if (exe_ctx) { 1231554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1232b9c1b51eSKate Stone if (thread) { 1233554f68d3SGreg Clayton const char *cstr = thread->GetName(); 1234b9c1b51eSKate Stone if (cstr && cstr[0]) { 1235554f68d3SGreg Clayton s.PutCString(cstr); 1236554f68d3SGreg Clayton return true; 1237554f68d3SGreg Clayton } 1238554f68d3SGreg Clayton } 1239554f68d3SGreg Clayton } 1240554f68d3SGreg Clayton return false; 1241554f68d3SGreg Clayton 1242554f68d3SGreg Clayton case Entry::Type::ThreadQueue: 1243b9c1b51eSKate Stone if (exe_ctx) { 1244554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1245b9c1b51eSKate Stone if (thread) { 1246554f68d3SGreg Clayton const char *cstr = thread->GetQueueName(); 1247b9c1b51eSKate Stone if (cstr && cstr[0]) { 1248554f68d3SGreg Clayton s.PutCString(cstr); 1249554f68d3SGreg Clayton return true; 1250554f68d3SGreg Clayton } 1251554f68d3SGreg Clayton } 1252554f68d3SGreg Clayton } 1253554f68d3SGreg Clayton return false; 1254554f68d3SGreg Clayton 1255554f68d3SGreg Clayton case Entry::Type::ThreadStopReason: 1256b9c1b51eSKate Stone if (exe_ctx) { 1257554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1258b9c1b51eSKate Stone if (thread) { 1259554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1260b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1261554f68d3SGreg Clayton const char *cstr = stop_info_sp->GetDescription(); 1262b9c1b51eSKate Stone if (cstr && cstr[0]) { 1263554f68d3SGreg Clayton s.PutCString(cstr); 1264554f68d3SGreg Clayton return true; 1265554f68d3SGreg Clayton } 1266554f68d3SGreg Clayton } 1267554f68d3SGreg Clayton } 1268554f68d3SGreg Clayton } 1269554f68d3SGreg Clayton return false; 1270554f68d3SGreg Clayton 1271554f68d3SGreg Clayton case Entry::Type::ThreadReturnValue: 1272b9c1b51eSKate Stone if (exe_ctx) { 1273554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1274b9c1b51eSKate Stone if (thread) { 1275554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1276b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1277b9c1b51eSKate Stone ValueObjectSP return_valobj_sp = 1278b9c1b51eSKate Stone StopInfo::GetReturnValueObject(stop_info_sp); 1279b9c1b51eSKate Stone if (return_valobj_sp) { 1280554f68d3SGreg Clayton return_valobj_sp->Dump(s); 1281554f68d3SGreg Clayton return true; 1282554f68d3SGreg Clayton } 1283554f68d3SGreg Clayton } 1284554f68d3SGreg Clayton } 1285554f68d3SGreg Clayton } 1286554f68d3SGreg Clayton return false; 1287554f68d3SGreg Clayton 1288554f68d3SGreg Clayton case Entry::Type::ThreadCompletedExpression: 1289b9c1b51eSKate Stone if (exe_ctx) { 1290554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1291b9c1b51eSKate Stone if (thread) { 1292554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1293b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1294b9c1b51eSKate Stone ExpressionVariableSP expression_var_sp = 1295b9c1b51eSKate Stone StopInfo::GetExpressionVariable(stop_info_sp); 1296b9c1b51eSKate Stone if (expression_var_sp && expression_var_sp->GetValueObject()) { 1297554f68d3SGreg Clayton expression_var_sp->GetValueObject()->Dump(s); 1298554f68d3SGreg Clayton return true; 1299554f68d3SGreg Clayton } 1300554f68d3SGreg Clayton } 1301554f68d3SGreg Clayton } 1302554f68d3SGreg Clayton } 1303554f68d3SGreg Clayton return false; 1304554f68d3SGreg Clayton 1305554f68d3SGreg Clayton case Entry::Type::ScriptThread: 1306b9c1b51eSKate Stone if (exe_ctx) { 1307554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1308554f68d3SGreg Clayton if (thread) 1309b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, thread, 1310b9c1b51eSKate Stone entry.string.c_str()); 1311554f68d3SGreg Clayton } 1312554f68d3SGreg Clayton return false; 1313554f68d3SGreg Clayton 1314554f68d3SGreg Clayton case Entry::Type::ThreadInfo: 1315b9c1b51eSKate Stone if (exe_ctx) { 1316554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1317b9c1b51eSKate Stone if (thread) { 1318554f68d3SGreg Clayton StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1319b9c1b51eSKate Stone if (object_sp && 1320b9c1b51eSKate Stone object_sp->GetType() == StructuredData::Type::eTypeDictionary) { 1321554f68d3SGreg Clayton if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) 1322554f68d3SGreg Clayton return true; 1323554f68d3SGreg Clayton } 1324554f68d3SGreg Clayton } 1325554f68d3SGreg Clayton } 1326554f68d3SGreg Clayton return false; 1327554f68d3SGreg Clayton 1328554f68d3SGreg Clayton case Entry::Type::TargetArch: 1329b9c1b51eSKate Stone if (exe_ctx) { 1330554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1331b9c1b51eSKate Stone if (target) { 1332554f68d3SGreg Clayton const ArchSpec &arch = target->GetArchitecture(); 1333b9c1b51eSKate Stone if (arch.IsValid()) { 1334554f68d3SGreg Clayton s.PutCString(arch.GetArchitectureName()); 1335554f68d3SGreg Clayton return true; 1336554f68d3SGreg Clayton } 1337554f68d3SGreg Clayton } 1338554f68d3SGreg Clayton } 1339554f68d3SGreg Clayton return false; 1340554f68d3SGreg Clayton 1341554f68d3SGreg Clayton case Entry::Type::ScriptTarget: 1342b9c1b51eSKate Stone if (exe_ctx) { 1343554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1344554f68d3SGreg Clayton if (target) 1345b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, target, 1346b9c1b51eSKate Stone entry.string.c_str()); 1347554f68d3SGreg Clayton } 1348554f68d3SGreg Clayton return false; 1349554f68d3SGreg Clayton 1350554f68d3SGreg Clayton case Entry::Type::ModuleFile: 1351b9c1b51eSKate Stone if (sc) { 1352554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1353b9c1b51eSKate Stone if (module) { 1354554f68d3SGreg Clayton if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1355554f68d3SGreg Clayton return true; 1356554f68d3SGreg Clayton } 1357554f68d3SGreg Clayton } 1358554f68d3SGreg Clayton return false; 1359554f68d3SGreg Clayton 1360554f68d3SGreg Clayton case Entry::Type::File: 1361b9c1b51eSKate Stone if (sc) { 1362554f68d3SGreg Clayton CompileUnit *cu = sc->comp_unit; 1363b9c1b51eSKate Stone if (cu) { 1364554f68d3SGreg Clayton // CompileUnit is a FileSpec 1365554f68d3SGreg Clayton if (DumpFile(s, *cu, (FileKind)entry.number)) 1366554f68d3SGreg Clayton return true; 1367554f68d3SGreg Clayton } 1368554f68d3SGreg Clayton } 1369554f68d3SGreg Clayton return false; 1370554f68d3SGreg Clayton 1371dc975670SDawn Perchik case Entry::Type::Lang: 1372b9c1b51eSKate Stone if (sc) { 1373dc975670SDawn Perchik CompileUnit *cu = sc->comp_unit; 1374b9c1b51eSKate Stone if (cu) { 1375b9c1b51eSKate Stone const char *lang_name = 1376b9c1b51eSKate Stone Language::GetNameForLanguageType(cu->GetLanguage()); 1377b9c1b51eSKate Stone if (lang_name) { 1378dc975670SDawn Perchik s.PutCString(lang_name); 1379dc975670SDawn Perchik return true; 1380dc975670SDawn Perchik } 1381dc975670SDawn Perchik } 1382dc975670SDawn Perchik } 1383dc975670SDawn Perchik return false; 1384dc975670SDawn Perchik 1385554f68d3SGreg Clayton case Entry::Type::FrameIndex: 1386b9c1b51eSKate Stone if (exe_ctx) { 1387554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1388b9c1b51eSKate Stone if (frame) { 1389554f68d3SGreg Clayton const char *format = "%" PRIu32; 1390554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1391554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1392554f68d3SGreg Clayton s.Printf(format, frame->GetFrameIndex()); 1393554f68d3SGreg Clayton return true; 1394554f68d3SGreg Clayton } 1395554f68d3SGreg Clayton } 1396554f68d3SGreg Clayton return false; 1397554f68d3SGreg Clayton 1398554f68d3SGreg Clayton case Entry::Type::FrameRegisterPC: 1399b9c1b51eSKate Stone if (exe_ctx) { 1400554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1401b9c1b51eSKate Stone if (frame) { 1402554f68d3SGreg Clayton const Address &pc_addr = frame->GetFrameCodeAddress(); 1403b9c1b51eSKate Stone if (pc_addr.IsValid()) { 1404554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) 1405554f68d3SGreg Clayton return true; 1406554f68d3SGreg Clayton } 1407554f68d3SGreg Clayton } 1408554f68d3SGreg Clayton } 1409554f68d3SGreg Clayton return false; 1410554f68d3SGreg Clayton 1411554f68d3SGreg Clayton case Entry::Type::FrameRegisterSP: 1412b9c1b51eSKate Stone if (exe_ctx) { 1413554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1414b9c1b51eSKate Stone if (frame) { 1415b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 1416b9c1b51eSKate Stone (lldb::Format)entry.number)) 1417554f68d3SGreg Clayton return true; 1418554f68d3SGreg Clayton } 1419554f68d3SGreg Clayton } 1420554f68d3SGreg Clayton return false; 1421554f68d3SGreg Clayton 1422554f68d3SGreg Clayton case Entry::Type::FrameRegisterFP: 1423b9c1b51eSKate Stone if (exe_ctx) { 1424554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1425b9c1b51eSKate Stone if (frame) { 1426b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, 1427b9c1b51eSKate Stone (lldb::Format)entry.number)) 1428554f68d3SGreg Clayton return true; 1429554f68d3SGreg Clayton } 1430554f68d3SGreg Clayton } 1431554f68d3SGreg Clayton return false; 1432554f68d3SGreg Clayton 1433554f68d3SGreg Clayton case Entry::Type::FrameRegisterFlags: 1434b9c1b51eSKate Stone if (exe_ctx) { 1435554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1436b9c1b51eSKate Stone if (frame) { 1437b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, 1438b9c1b51eSKate Stone LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1439554f68d3SGreg Clayton return true; 1440554f68d3SGreg Clayton } 1441554f68d3SGreg Clayton } 1442554f68d3SGreg Clayton return false; 1443554f68d3SGreg Clayton 14446a9767c7SJim Ingham case Entry::Type::FrameNoDebug: 14456a9767c7SJim Ingham if (exe_ctx) { 14466a9767c7SJim Ingham StackFrame *frame = exe_ctx->GetFramePtr(); 14476a9767c7SJim Ingham if (frame) { 14486a9767c7SJim Ingham return !frame->HasDebugInformation(); 14496a9767c7SJim Ingham } 14506a9767c7SJim Ingham } 14516a9767c7SJim Ingham return true; 14526a9767c7SJim Ingham 1453554f68d3SGreg Clayton case Entry::Type::FrameRegisterByName: 1454b9c1b51eSKate Stone if (exe_ctx) { 1455554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1456b9c1b51eSKate Stone if (frame) { 1457b9c1b51eSKate Stone if (DumpRegister(s, frame, entry.string.c_str(), 1458b9c1b51eSKate Stone (lldb::Format)entry.number)) 1459554f68d3SGreg Clayton return true; 1460554f68d3SGreg Clayton } 1461554f68d3SGreg Clayton } 1462554f68d3SGreg Clayton return false; 1463554f68d3SGreg Clayton 1464554f68d3SGreg Clayton case Entry::Type::ScriptFrame: 1465b9c1b51eSKate Stone if (exe_ctx) { 1466554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1467554f68d3SGreg Clayton if (frame) 1468b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, frame, 1469b9c1b51eSKate Stone entry.string.c_str()); 1470554f68d3SGreg Clayton } 1471554f68d3SGreg Clayton return false; 1472554f68d3SGreg Clayton 1473554f68d3SGreg Clayton case Entry::Type::FunctionID: 1474b9c1b51eSKate Stone if (sc) { 1475b9c1b51eSKate Stone if (sc->function) { 1476554f68d3SGreg Clayton s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1477554f68d3SGreg Clayton return true; 1478b9c1b51eSKate Stone } else if (sc->symbol) { 1479554f68d3SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 1480554f68d3SGreg Clayton return true; 1481554f68d3SGreg Clayton } 1482554f68d3SGreg Clayton } 1483554f68d3SGreg Clayton return false; 1484554f68d3SGreg Clayton 1485554f68d3SGreg Clayton case Entry::Type::FunctionDidChange: 1486554f68d3SGreg Clayton return function_changed; 1487554f68d3SGreg Clayton 1488554f68d3SGreg Clayton case Entry::Type::FunctionInitialFunction: 1489554f68d3SGreg Clayton return initial_function; 1490554f68d3SGreg Clayton 1491b9c1b51eSKate Stone case Entry::Type::FunctionName: { 1492d4129b47SEnrico Granata Language *language_plugin = nullptr; 1493d4129b47SEnrico Granata bool language_plugin_handled = false; 1494d4129b47SEnrico Granata StreamString ss; 1495d4129b47SEnrico Granata if (sc->function) 1496d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1497d4129b47SEnrico Granata else if (sc->symbol) 1498d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1499b9c1b51eSKate Stone if (language_plugin) { 1500b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1501b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); 1502d4129b47SEnrico Granata } 1503b9c1b51eSKate Stone if (language_plugin_handled) { 1504c156427dSZachary Turner s << ss.GetString(); 1505d4129b47SEnrico Granata return true; 1506b9c1b51eSKate Stone } else { 1507a74f37a5SEugene Zelenko const char *name = nullptr; 1508554f68d3SGreg Clayton if (sc->function) 1509a74f37a5SEugene Zelenko name = sc->function->GetName().AsCString(nullptr); 1510554f68d3SGreg Clayton else if (sc->symbol) 1511a74f37a5SEugene Zelenko name = sc->symbol->GetName().AsCString(nullptr); 1512b9c1b51eSKate Stone if (name) { 1513554f68d3SGreg Clayton s.PutCString(name); 1514554f68d3SGreg Clayton 1515b9c1b51eSKate Stone if (sc->block) { 1516554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1517b9c1b51eSKate Stone if (inline_block) { 1518b9c1b51eSKate Stone const InlineFunctionInfo *inline_info = 1519b9c1b51eSKate Stone sc->block->GetInlinedFunctionInfo(); 1520b9c1b51eSKate Stone if (inline_info) { 1521554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1522ddaf6a72SGreg Clayton inline_info->GetName(sc->function->GetLanguage()).Dump(&s); 1523554f68d3SGreg Clayton } 1524554f68d3SGreg Clayton } 1525554f68d3SGreg Clayton } 1526554f68d3SGreg Clayton return true; 1527554f68d3SGreg Clayton } 1528554f68d3SGreg Clayton } 1529d4129b47SEnrico Granata } 1530554f68d3SGreg Clayton return false; 1531554f68d3SGreg Clayton 1532b9c1b51eSKate Stone case Entry::Type::FunctionNameNoArgs: { 1533d4129b47SEnrico Granata Language *language_plugin = nullptr; 1534d4129b47SEnrico Granata bool language_plugin_handled = false; 1535d4129b47SEnrico Granata StreamString ss; 1536d4129b47SEnrico Granata if (sc->function) 1537d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1538d4129b47SEnrico Granata else if (sc->symbol) 1539d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1540b9c1b51eSKate Stone if (language_plugin) { 1541b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1542b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, 1543d4129b47SEnrico Granata ss); 1544d4129b47SEnrico Granata } 1545b9c1b51eSKate Stone if (language_plugin_handled) { 1546c156427dSZachary Turner s << ss.GetString(); 1547d4129b47SEnrico Granata return true; 1548b9c1b51eSKate Stone } else { 1549554f68d3SGreg Clayton ConstString name; 1550554f68d3SGreg Clayton if (sc->function) 1551ddaf6a72SGreg Clayton name = sc->function->GetNameNoArguments(); 1552554f68d3SGreg Clayton else if (sc->symbol) 1553ddaf6a72SGreg Clayton name = sc->symbol->GetNameNoArguments(); 1554b9c1b51eSKate Stone if (name) { 1555554f68d3SGreg Clayton s.PutCString(name.GetCString()); 1556554f68d3SGreg Clayton return true; 1557554f68d3SGreg Clayton } 1558554f68d3SGreg Clayton } 1559d4129b47SEnrico Granata } 1560554f68d3SGreg Clayton return false; 1561554f68d3SGreg Clayton 1562b9c1b51eSKate Stone case Entry::Type::FunctionNameWithArgs: { 1563d4129b47SEnrico Granata Language *language_plugin = nullptr; 1564d4129b47SEnrico Granata bool language_plugin_handled = false; 1565d4129b47SEnrico Granata StreamString ss; 1566d4129b47SEnrico Granata if (sc->function) 1567d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1568d4129b47SEnrico Granata else if (sc->symbol) 1569d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1570b9c1b51eSKate Stone if (language_plugin) { 1571b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1572b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); 1573d4129b47SEnrico Granata } 1574b9c1b51eSKate Stone if (language_plugin_handled) { 1575c156427dSZachary Turner s << ss.GetString(); 1576d4129b47SEnrico Granata return true; 1577b9c1b51eSKate Stone } else { 1578554f68d3SGreg Clayton // Print the function name with arguments in it 1579b9c1b51eSKate Stone if (sc->function) { 1580b9c1b51eSKate Stone ExecutionContextScope *exe_scope = 1581b9c1b51eSKate Stone exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 1582a74f37a5SEugene Zelenko const char *cstr = sc->function->GetName().AsCString(nullptr); 1583b9c1b51eSKate Stone if (cstr) { 1584a74f37a5SEugene Zelenko const InlineFunctionInfo *inline_info = nullptr; 1585554f68d3SGreg Clayton VariableListSP variable_list_sp; 1586554f68d3SGreg Clayton bool get_function_vars = true; 1587b9c1b51eSKate Stone if (sc->block) { 1588554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1589554f68d3SGreg Clayton 1590b9c1b51eSKate Stone if (inline_block) { 1591554f68d3SGreg Clayton get_function_vars = false; 1592554f68d3SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 1593554f68d3SGreg Clayton if (inline_info) 1594554f68d3SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList(true); 1595554f68d3SGreg Clayton } 1596554f68d3SGreg Clayton } 1597554f68d3SGreg Clayton 1598b9c1b51eSKate Stone if (get_function_vars) { 1599b9c1b51eSKate Stone variable_list_sp = 1600b9c1b51eSKate Stone sc->function->GetBlock(true).GetBlockVariableList(true); 1601554f68d3SGreg Clayton } 1602554f68d3SGreg Clayton 1603b9c1b51eSKate Stone if (inline_info) { 1604554f68d3SGreg Clayton s.PutCString(cstr); 1605554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1606b9c1b51eSKate Stone cstr = 1607b9c1b51eSKate Stone inline_info->GetName(sc->function->GetLanguage()).GetCString(); 1608554f68d3SGreg Clayton } 1609554f68d3SGreg Clayton 1610554f68d3SGreg Clayton VariableList args; 1611554f68d3SGreg Clayton if (variable_list_sp) 1612b9c1b51eSKate Stone variable_list_sp->AppendVariablesWithScope( 1613b9c1b51eSKate Stone eValueTypeVariableArgument, args); 1614b9c1b51eSKate Stone if (args.GetSize() > 0) { 1615554f68d3SGreg Clayton const char *open_paren = strchr(cstr, '('); 1616554f68d3SGreg Clayton const char *close_paren = nullptr; 1617554f68d3SGreg Clayton const char *generic = strchr(cstr, '<'); 1618554f68d3SGreg Clayton // if before the arguments list begins there is a template sign 1619554f68d3SGreg Clayton // then scan to the end of the generic args before you try to find 1620554f68d3SGreg Clayton // the arguments list 1621b9c1b51eSKate Stone if (generic && open_paren && generic < open_paren) { 1622554f68d3SGreg Clayton int generic_depth = 1; 1623554f68d3SGreg Clayton ++generic; 1624b9c1b51eSKate Stone for (; *generic && generic_depth > 0; generic++) { 1625554f68d3SGreg Clayton if (*generic == '<') 1626554f68d3SGreg Clayton generic_depth++; 1627554f68d3SGreg Clayton if (*generic == '>') 1628554f68d3SGreg Clayton generic_depth--; 1629554f68d3SGreg Clayton } 1630554f68d3SGreg Clayton if (*generic) 1631554f68d3SGreg Clayton open_paren = strchr(generic, '('); 1632554f68d3SGreg Clayton else 1633554f68d3SGreg Clayton open_paren = nullptr; 1634554f68d3SGreg Clayton } 1635b9c1b51eSKate Stone if (open_paren) { 1636b9c1b51eSKate Stone if (IsToken(open_paren, "(anonymous namespace)")) { 1637b9c1b51eSKate Stone open_paren = 1638b9c1b51eSKate Stone strchr(open_paren + strlen("(anonymous namespace)"), '('); 1639554f68d3SGreg Clayton if (open_paren) 1640554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1641b9c1b51eSKate Stone } else 1642554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1643554f68d3SGreg Clayton } 1644554f68d3SGreg Clayton 1645554f68d3SGreg Clayton if (open_paren) 1646554f68d3SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 1647b9c1b51eSKate Stone else { 1648554f68d3SGreg Clayton s.PutCString(cstr); 1649554f68d3SGreg Clayton s.PutChar('('); 1650554f68d3SGreg Clayton } 1651554f68d3SGreg Clayton const size_t num_args = args.GetSize(); 1652b9c1b51eSKate Stone for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { 1653554f68d3SGreg Clayton std::string buffer; 1654554f68d3SGreg Clayton 1655554f68d3SGreg Clayton VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); 1656b9c1b51eSKate Stone ValueObjectSP var_value_sp( 1657b9c1b51eSKate Stone ValueObjectVariable::Create(exe_scope, var_sp)); 1658ad91c7ceSEnrico Granata StreamString ss; 1659c156427dSZachary Turner llvm::StringRef var_representation; 1660554f68d3SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 1661b9c1b51eSKate Stone if (var_value_sp->GetCompilerType().IsValid()) { 1662ad91c7ceSEnrico Granata if (var_value_sp && exe_scope->CalculateTarget()) 1663b9c1b51eSKate Stone var_value_sp = 1664b9c1b51eSKate Stone var_value_sp->GetQualifiedRepresentationIfAvailable( 1665b9c1b51eSKate Stone exe_scope->CalculateTarget() 1666b9c1b51eSKate Stone ->TargetProperties::GetPreferDynamicValue(), 1667b9c1b51eSKate Stone exe_scope->CalculateTarget() 1668b9c1b51eSKate Stone ->TargetProperties::GetEnableSyntheticValue()); 166999558cc4SGreg Clayton if (var_value_sp->GetCompilerType().IsAggregateType() && 1670b9c1b51eSKate Stone DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { 1671b9c1b51eSKate Stone static StringSummaryFormat format( 1672b9c1b51eSKate Stone TypeSummaryImpl::Flags() 1673554f68d3SGreg Clayton .SetHideItemNames(false) 1674554f68d3SGreg Clayton .SetShowMembersOneLiner(true), 1675554f68d3SGreg Clayton ""); 1676b9c1b51eSKate Stone format.FormatObject(var_value_sp.get(), buffer, 1677b9c1b51eSKate Stone TypeSummaryOptions()); 1678c156427dSZachary Turner var_representation = buffer; 1679b9c1b51eSKate Stone } else 1680b9c1b51eSKate Stone var_value_sp->DumpPrintableRepresentation( 1681b9c1b51eSKate Stone ss, ValueObject::ValueObjectRepresentationStyle:: 1682b9c1b51eSKate Stone eValueObjectRepresentationStyleSummary, 1683ad91c7ceSEnrico Granata eFormatDefault, 168465d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eAllow, 1685ad91c7ceSEnrico Granata false); 1686ad91c7ceSEnrico Granata } 1687ad91c7ceSEnrico Granata 1688c156427dSZachary Turner if (!ss.GetString().empty()) 1689c156427dSZachary Turner var_representation = ss.GetString(); 1690554f68d3SGreg Clayton if (arg_idx > 0) 1691554f68d3SGreg Clayton s.PutCString(", "); 1692b9c1b51eSKate Stone if (var_value_sp->GetError().Success()) { 1693c156427dSZachary Turner if (!var_representation.empty()) 1694c156427dSZachary Turner s.Printf("%s=%s", var_name, var_representation.str().c_str()); 1695554f68d3SGreg Clayton else 1696b9c1b51eSKate Stone s.Printf("%s=%s at %s", var_name, 1697b9c1b51eSKate Stone var_value_sp->GetTypeName().GetCString(), 1698b9c1b51eSKate Stone var_value_sp->GetLocationAsCString()); 1699b9c1b51eSKate Stone } else 1700554f68d3SGreg Clayton s.Printf("%s=<unavailable>", var_name); 1701554f68d3SGreg Clayton } 1702554f68d3SGreg Clayton 1703554f68d3SGreg Clayton if (close_paren) 1704554f68d3SGreg Clayton s.PutCString(close_paren); 1705554f68d3SGreg Clayton else 1706554f68d3SGreg Clayton s.PutChar(')'); 1707554f68d3SGreg Clayton 1708b9c1b51eSKate Stone } else { 1709554f68d3SGreg Clayton s.PutCString(cstr); 1710554f68d3SGreg Clayton } 1711554f68d3SGreg Clayton return true; 1712554f68d3SGreg Clayton } 1713b9c1b51eSKate Stone } else if (sc->symbol) { 1714a74f37a5SEugene Zelenko const char *cstr = sc->symbol->GetName().AsCString(nullptr); 1715b9c1b51eSKate Stone if (cstr) { 1716554f68d3SGreg Clayton s.PutCString(cstr); 1717554f68d3SGreg Clayton return true; 1718554f68d3SGreg Clayton } 1719554f68d3SGreg Clayton } 1720554f68d3SGreg Clayton } 1721d4129b47SEnrico Granata } 1722554f68d3SGreg Clayton return false; 1723554f68d3SGreg Clayton 1724554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffset: 1725b9c1b51eSKate Stone if (addr) { 1726b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, 1727b9c1b51eSKate Stone false)) 1728554f68d3SGreg Clayton return true; 1729554f68d3SGreg Clayton } 1730554f68d3SGreg Clayton return false; 1731554f68d3SGreg Clayton 1732554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffsetConcrete: 1733b9c1b51eSKate Stone if (addr) { 1734b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, 1735b9c1b51eSKate Stone true)) 1736554f68d3SGreg Clayton return true; 1737554f68d3SGreg Clayton } 1738554f68d3SGreg Clayton return false; 1739554f68d3SGreg Clayton 1740554f68d3SGreg Clayton case Entry::Type::FunctionLineOffset: 1741b9c1b51eSKate Stone return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1742b9c1b51eSKate Stone sc->line_entry.range.GetBaseAddress(), 1743b9c1b51eSKate Stone false, false, false)); 1744554f68d3SGreg Clayton 1745554f68d3SGreg Clayton case Entry::Type::FunctionPCOffset: 1746b9c1b51eSKate Stone if (exe_ctx) { 1747554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1748b9c1b51eSKate Stone if (frame) { 1749b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1750b9c1b51eSKate Stone frame->GetFrameCodeAddress(), false, 1751b9c1b51eSKate Stone false, false)) 1752554f68d3SGreg Clayton return true; 1753554f68d3SGreg Clayton } 1754554f68d3SGreg Clayton } 1755554f68d3SGreg Clayton return false; 1756554f68d3SGreg Clayton 1757c980fa92SJason Molenda case Entry::Type::FunctionChanged: 1758a74f37a5SEugene Zelenko return function_changed; 1759c980fa92SJason Molenda 1760b9c1b51eSKate Stone case Entry::Type::FunctionIsOptimized: { 17616ab659a9SJason Molenda bool is_optimized = false; 1762b9c1b51eSKate Stone if (sc->function && sc->function->GetIsOptimized()) { 17636ab659a9SJason Molenda is_optimized = true; 17646ab659a9SJason Molenda } 17656ab659a9SJason Molenda return is_optimized; 17666ab659a9SJason Molenda } 17676ab659a9SJason Molenda 1768c980fa92SJason Molenda case Entry::Type::FunctionInitial: 1769a74f37a5SEugene Zelenko return initial_function; 1770c980fa92SJason Molenda 1771554f68d3SGreg Clayton case Entry::Type::LineEntryFile: 1772b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1773554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1774b9c1b51eSKate Stone if (module) { 1775554f68d3SGreg Clayton if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1776554f68d3SGreg Clayton return true; 1777554f68d3SGreg Clayton } 1778554f68d3SGreg Clayton } 1779554f68d3SGreg Clayton return false; 1780554f68d3SGreg Clayton 1781554f68d3SGreg Clayton case Entry::Type::LineEntryLineNumber: 1782b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1783554f68d3SGreg Clayton const char *format = "%" PRIu32; 1784554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1785554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1786554f68d3SGreg Clayton s.Printf(format, sc->line_entry.line); 1787554f68d3SGreg Clayton return true; 1788554f68d3SGreg Clayton } 1789554f68d3SGreg Clayton return false; 1790554f68d3SGreg Clayton 1791554f68d3SGreg Clayton case Entry::Type::LineEntryStartAddress: 1792554f68d3SGreg Clayton case Entry::Type::LineEntryEndAddress: 1793b9c1b51eSKate Stone if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { 1794554f68d3SGreg Clayton Address addr = sc->line_entry.range.GetBaseAddress(); 1795554f68d3SGreg Clayton 1796554f68d3SGreg Clayton if (entry.type == Entry::Type::LineEntryEndAddress) 1797554f68d3SGreg Clayton addr.Slide(sc->line_entry.range.GetByteSize()); 1798554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, addr, false)) 1799554f68d3SGreg Clayton return true; 1800554f68d3SGreg Clayton } 1801554f68d3SGreg Clayton return false; 1802554f68d3SGreg Clayton 1803554f68d3SGreg Clayton case Entry::Type::CurrentPCArrow: 1804b9c1b51eSKate Stone if (addr && exe_ctx && exe_ctx->GetFramePtr()) { 1805b9c1b51eSKate Stone RegisterContextSP reg_ctx = 1806b9c1b51eSKate Stone exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1807b9c1b51eSKate Stone if (reg_ctx) { 1808554f68d3SGreg Clayton addr_t pc_loadaddr = reg_ctx->GetPC(); 1809b9c1b51eSKate Stone if (pc_loadaddr != LLDB_INVALID_ADDRESS) { 1810554f68d3SGreg Clayton Address pc; 1811554f68d3SGreg Clayton pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); 1812b9c1b51eSKate Stone if (pc == *addr) { 1813554f68d3SGreg Clayton s.Printf("-> "); 1814554f68d3SGreg Clayton return true; 1815554f68d3SGreg Clayton } 1816554f68d3SGreg Clayton } 1817554f68d3SGreg Clayton } 1818554f68d3SGreg Clayton s.Printf(" "); 1819554f68d3SGreg Clayton return true; 1820554f68d3SGreg Clayton } 1821554f68d3SGreg Clayton return false; 1822554f68d3SGreg Clayton } 1823554f68d3SGreg Clayton return false; 1824554f68d3SGreg Clayton } 1825554f68d3SGreg Clayton 1826b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames( 1827b9c1b51eSKate Stone Stream &s, const FormatEntity::Entry::Definition *parent) { 1828b9c1b51eSKate Stone if (parent->children) { 1829554f68d3SGreg Clayton const size_t n = parent->num_children; 1830b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1831554f68d3SGreg Clayton if (i > 0) 1832554f68d3SGreg Clayton s.PutCString(", "); 1833554f68d3SGreg Clayton s.Printf("\"%s\"", parent->children[i].name); 1834554f68d3SGreg Clayton } 1835554f68d3SGreg Clayton return true; 1836554f68d3SGreg Clayton } 1837554f68d3SGreg Clayton return false; 1838554f68d3SGreg Clayton } 1839554f68d3SGreg Clayton 1840b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str, 1841554f68d3SGreg Clayton const FormatEntity::Entry::Definition *parent, 1842b9c1b51eSKate Stone FormatEntity::Entry &entry) { 1843554f68d3SGreg Clayton Error error; 1844554f68d3SGreg Clayton 1845554f68d3SGreg Clayton const size_t sep_pos = format_str.find_first_of(".[:"); 1846b9c1b51eSKate Stone const char sep_char = 1847b9c1b51eSKate Stone (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1848554f68d3SGreg Clayton llvm::StringRef key = format_str.substr(0, sep_pos); 1849554f68d3SGreg Clayton 1850554f68d3SGreg Clayton const size_t n = parent->num_children; 1851b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1852554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1853b9c1b51eSKate Stone if (key.equals(entry_def->name) || entry_def->name[0] == '*') { 1854554f68d3SGreg Clayton llvm::StringRef value; 1855554f68d3SGreg Clayton if (sep_char) 1856b9c1b51eSKate Stone value = 1857b9c1b51eSKate Stone format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1858b9c1b51eSKate Stone switch (entry_def->type) { 1859554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentString: 18603a29f8b9SPavel Labath entry.string = format_str.str(); 1861554f68d3SGreg Clayton return error; // Success 1862554f68d3SGreg Clayton 1863554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentNumber: 1864554f68d3SGreg Clayton entry.number = entry_def->data; 1865554f68d3SGreg Clayton return error; // Success 1866554f68d3SGreg Clayton 1867554f68d3SGreg Clayton case FormatEntity::Entry::Type::InsertString: 1868554f68d3SGreg Clayton entry.type = entry_def->type; 1869554f68d3SGreg Clayton entry.string = entry_def->string; 1870554f68d3SGreg Clayton return error; // Success 1871554f68d3SGreg Clayton 1872554f68d3SGreg Clayton default: 1873554f68d3SGreg Clayton entry.type = entry_def->type; 1874554f68d3SGreg Clayton break; 1875554f68d3SGreg Clayton } 1876554f68d3SGreg Clayton 1877b9c1b51eSKate Stone if (value.empty()) { 1878b9c1b51eSKate Stone if (entry_def->type == FormatEntity::Entry::Type::Invalid) { 1879b9c1b51eSKate Stone if (entry_def->children) { 1880554f68d3SGreg Clayton StreamString error_strm; 1881b9c1b51eSKate Stone error_strm.Printf("'%s' can't be specified on its own, you must " 1882b9c1b51eSKate Stone "access one of its children: ", 1883b9c1b51eSKate Stone entry_def->name); 1884554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, entry_def); 1885c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1886b9c1b51eSKate Stone } else if (sep_char == ':') { 1887b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1888b9c1b51eSKate Stone // string argument 1889554f68d3SGreg Clayton // that needs to be stored in the entry (like "${script.var:}"). 1890554f68d3SGreg Clayton // In this case the string value is the empty string which is ok. 1891b9c1b51eSKate Stone } else { 1892554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1893554f68d3SGreg Clayton } 1894554f68d3SGreg Clayton } 1895b9c1b51eSKate Stone } else { 1896b9c1b51eSKate Stone if (entry_def->children) { 1897554f68d3SGreg Clayton error = ParseEntry(value, entry_def, entry); 1898b9c1b51eSKate Stone } else if (sep_char == ':') { 1899b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 1900b9c1b51eSKate Stone // string argument 1901b9c1b51eSKate Stone // that needs to be stored in the entry (like 1902b9c1b51eSKate Stone // "${script.var:modulename.function}") 19033a29f8b9SPavel Labath entry.string = value.str(); 1904b9c1b51eSKate Stone } else { 1905b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1906b9c1b51eSKate Stone "'%s' followed by '%s' but it has no children", key.str().c_str(), 1907554f68d3SGreg Clayton value.str().c_str()); 1908554f68d3SGreg Clayton } 1909554f68d3SGreg Clayton } 1910554f68d3SGreg Clayton return error; 1911554f68d3SGreg Clayton } 1912554f68d3SGreg Clayton } 1913554f68d3SGreg Clayton StreamString error_strm; 1914554f68d3SGreg Clayton if (parent->type == FormatEntity::Entry::Type::Root) 1915b9c1b51eSKate Stone error_strm.Printf( 1916b9c1b51eSKate Stone "invalid top level item '%s'. Valid top level items are: ", 1917b9c1b51eSKate Stone key.str().c_str()); 1918554f68d3SGreg Clayton else 1919b9c1b51eSKate Stone error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", 1920b9c1b51eSKate Stone key.str().c_str(), parent->name); 1921554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, parent); 1922c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1923554f68d3SGreg Clayton return error; 1924554f68d3SGreg Clayton } 1925554f68d3SGreg Clayton 1926554f68d3SGreg Clayton static const FormatEntity::Entry::Definition * 1927b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str, 1928b9c1b51eSKate Stone const FormatEntity::Entry::Definition *parent, 1929b9c1b51eSKate Stone llvm::StringRef &remainder) { 1930554f68d3SGreg Clayton Error error; 1931554f68d3SGreg Clayton 1932554f68d3SGreg Clayton std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 1933554f68d3SGreg Clayton const size_t n = parent->num_children; 1934b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1935554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1936b9c1b51eSKate Stone if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { 1937b9c1b51eSKate Stone if (p.second.empty()) { 1938554f68d3SGreg Clayton if (format_str.back() == '.') 1939554f68d3SGreg Clayton remainder = format_str.drop_front(format_str.size() - 1); 1940554f68d3SGreg Clayton else 1941554f68d3SGreg Clayton remainder = llvm::StringRef(); // Exact match 1942554f68d3SGreg Clayton return entry_def; 1943b9c1b51eSKate Stone } else { 1944b9c1b51eSKate Stone if (entry_def->children) { 1945554f68d3SGreg Clayton return FindEntry(p.second, entry_def, remainder); 1946b9c1b51eSKate Stone } else { 1947554f68d3SGreg Clayton remainder = p.second; 1948554f68d3SGreg Clayton return entry_def; 1949554f68d3SGreg Clayton } 1950554f68d3SGreg Clayton } 1951554f68d3SGreg Clayton } 1952554f68d3SGreg Clayton } 1953554f68d3SGreg Clayton remainder = format_str; 1954554f68d3SGreg Clayton return parent; 1955554f68d3SGreg Clayton } 1956554f68d3SGreg Clayton 1957b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, 1958b9c1b51eSKate Stone uint32_t depth) { 1959554f68d3SGreg Clayton Error error; 1960b9c1b51eSKate Stone while (!format.empty() && error.Success()) { 1961554f68d3SGreg Clayton const size_t non_special_chars = format.find_first_of("${}\\"); 1962554f68d3SGreg Clayton 1963b9c1b51eSKate Stone if (non_special_chars == llvm::StringRef::npos) { 1964554f68d3SGreg Clayton // No special characters, just string bytes so add them and we are done 1965554f68d3SGreg Clayton parent_entry.AppendText(format); 1966554f68d3SGreg Clayton return error; 1967554f68d3SGreg Clayton } 1968554f68d3SGreg Clayton 1969b9c1b51eSKate Stone if (non_special_chars > 0) { 1970b9c1b51eSKate Stone // We have a special character, so add all characters before these as a 1971b9c1b51eSKate Stone // plain string 1972554f68d3SGreg Clayton parent_entry.AppendText(format.substr(0, non_special_chars)); 1973554f68d3SGreg Clayton format = format.drop_front(non_special_chars); 1974554f68d3SGreg Clayton } 1975554f68d3SGreg Clayton 1976b9c1b51eSKate Stone switch (format[0]) { 1977554f68d3SGreg Clayton case '\0': 1978554f68d3SGreg Clayton return error; 1979554f68d3SGreg Clayton 1980b9c1b51eSKate Stone case '{': { 1981554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 1982554f68d3SGreg Clayton Entry scope_entry(Entry::Type::Scope); 1983554f68d3SGreg Clayton error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); 1984554f68d3SGreg Clayton if (error.Fail()) 1985554f68d3SGreg Clayton return error; 1986554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(scope_entry)); 1987b9c1b51eSKate Stone } break; 1988554f68d3SGreg Clayton 1989554f68d3SGreg Clayton case '}': 1990554f68d3SGreg Clayton if (depth == 0) 1991554f68d3SGreg Clayton error.SetErrorString("unmatched '}' character"); 1992554f68d3SGreg Clayton else 1993b9c1b51eSKate Stone format = 1994b9c1b51eSKate Stone format 1995b9c1b51eSKate Stone .drop_front(); // Skip the '}' as we are at the end of the scope 1996554f68d3SGreg Clayton return error; 1997554f68d3SGreg Clayton 1998b9c1b51eSKate Stone case '\\': { 1999554f68d3SGreg Clayton format = format.drop_front(); // Skip the '\' character 2000b9c1b51eSKate Stone if (format.empty()) { 2001b9c1b51eSKate Stone error.SetErrorString( 2002b9c1b51eSKate Stone "'\\' character was not followed by another character"); 2003554f68d3SGreg Clayton return error; 2004554f68d3SGreg Clayton } 2005554f68d3SGreg Clayton 2006554f68d3SGreg Clayton const char desens_char = format[0]; 2007554f68d3SGreg Clayton format = format.drop_front(); // Skip the desensitized char character 2008b9c1b51eSKate Stone switch (desens_char) { 2009b9c1b51eSKate Stone case 'a': 2010b9c1b51eSKate Stone parent_entry.AppendChar('\a'); 2011b9c1b51eSKate Stone break; 2012b9c1b51eSKate Stone case 'b': 2013b9c1b51eSKate Stone parent_entry.AppendChar('\b'); 2014b9c1b51eSKate Stone break; 2015b9c1b51eSKate Stone case 'f': 2016b9c1b51eSKate Stone parent_entry.AppendChar('\f'); 2017b9c1b51eSKate Stone break; 2018b9c1b51eSKate Stone case 'n': 2019b9c1b51eSKate Stone parent_entry.AppendChar('\n'); 2020b9c1b51eSKate Stone break; 2021b9c1b51eSKate Stone case 'r': 2022b9c1b51eSKate Stone parent_entry.AppendChar('\r'); 2023b9c1b51eSKate Stone break; 2024b9c1b51eSKate Stone case 't': 2025b9c1b51eSKate Stone parent_entry.AppendChar('\t'); 2026b9c1b51eSKate Stone break; 2027b9c1b51eSKate Stone case 'v': 2028b9c1b51eSKate Stone parent_entry.AppendChar('\v'); 2029b9c1b51eSKate Stone break; 2030b9c1b51eSKate Stone case '\'': 2031b9c1b51eSKate Stone parent_entry.AppendChar('\''); 2032b9c1b51eSKate Stone break; 2033b9c1b51eSKate Stone case '\\': 2034b9c1b51eSKate Stone parent_entry.AppendChar('\\'); 2035b9c1b51eSKate Stone break; 2036554f68d3SGreg Clayton case '0': 2037554f68d3SGreg Clayton // 1 to 3 octal chars 2038554f68d3SGreg Clayton { 2039554f68d3SGreg Clayton // Make a string that can hold onto the initial zero char, 2040554f68d3SGreg Clayton // up to 3 octal digits, and a terminating NULL. 2041554f68d3SGreg Clayton char oct_str[5] = {0, 0, 0, 0, 0}; 2042554f68d3SGreg Clayton 2043554f68d3SGreg Clayton int i; 2044554f68d3SGreg Clayton for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) 2045554f68d3SGreg Clayton oct_str[i] = format[i]; 2046554f68d3SGreg Clayton 2047554f68d3SGreg Clayton // We don't want to consume the last octal character since 2048554f68d3SGreg Clayton // the main for loop will do this for us, so we advance p by 2049554f68d3SGreg Clayton // one less than i (even if i is zero) 2050554f68d3SGreg Clayton format = format.drop_front(i); 2051a74f37a5SEugene Zelenko unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); 2052b9c1b51eSKate Stone if (octal_value <= UINT8_MAX) { 2053554f68d3SGreg Clayton parent_entry.AppendChar((char)octal_value); 2054b9c1b51eSKate Stone } else { 2055554f68d3SGreg Clayton error.SetErrorString("octal number is larger than a single byte"); 2056554f68d3SGreg Clayton return error; 2057554f68d3SGreg Clayton } 2058554f68d3SGreg Clayton } 2059554f68d3SGreg Clayton break; 2060554f68d3SGreg Clayton 2061554f68d3SGreg Clayton case 'x': 2062554f68d3SGreg Clayton // hex number in the format 2063b9c1b51eSKate Stone if (isxdigit(format[0])) { 2064554f68d3SGreg Clayton // Make a string that can hold onto two hex chars plus a 2065554f68d3SGreg Clayton // NULL terminator 2066554f68d3SGreg Clayton char hex_str[3] = {0, 0, 0}; 2067554f68d3SGreg Clayton hex_str[0] = format[0]; 2068554f68d3SGreg Clayton 2069554f68d3SGreg Clayton format = format.drop_front(); 2070554f68d3SGreg Clayton 2071b9c1b51eSKate Stone if (isxdigit(format[0])) { 2072554f68d3SGreg Clayton hex_str[1] = format[0]; 2073554f68d3SGreg Clayton format = format.drop_front(); 2074554f68d3SGreg Clayton } 2075554f68d3SGreg Clayton 2076a74f37a5SEugene Zelenko unsigned long hex_value = strtoul(hex_str, nullptr, 16); 2077b9c1b51eSKate Stone if (hex_value <= UINT8_MAX) { 2078554f68d3SGreg Clayton parent_entry.AppendChar((char)hex_value); 2079b9c1b51eSKate Stone } else { 2080554f68d3SGreg Clayton error.SetErrorString("hex number is larger than a single byte"); 2081554f68d3SGreg Clayton return error; 2082554f68d3SGreg Clayton } 2083b9c1b51eSKate Stone } else { 2084554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2085554f68d3SGreg Clayton } 2086554f68d3SGreg Clayton break; 2087554f68d3SGreg Clayton 2088554f68d3SGreg Clayton default: 2089554f68d3SGreg Clayton // Just desensitize any other character by just printing what 2090554f68d3SGreg Clayton // came after the '\' 2091554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2092554f68d3SGreg Clayton break; 2093554f68d3SGreg Clayton } 2094b9c1b51eSKate Stone } break; 2095554f68d3SGreg Clayton 2096554f68d3SGreg Clayton case '$': 2097b9c1b51eSKate Stone if (format.size() == 1) { 2098554f68d3SGreg Clayton // '$' at the end of a format string, just print the '$' 2099554f68d3SGreg Clayton parent_entry.AppendText("$"); 2100b9c1b51eSKate Stone } else { 2101554f68d3SGreg Clayton format = format.drop_front(); // Skip the '$' 2102554f68d3SGreg Clayton 2103b9c1b51eSKate Stone if (format[0] == '{') { 2104554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2105554f68d3SGreg Clayton 2106554f68d3SGreg Clayton llvm::StringRef variable, variable_format; 2107b9c1b51eSKate Stone error = FormatEntity::ExtractVariableInfo(format, variable, 2108b9c1b51eSKate Stone variable_format); 2109554f68d3SGreg Clayton if (error.Fail()) 2110554f68d3SGreg Clayton return error; 2111554f68d3SGreg Clayton bool verify_is_thread_id = false; 2112554f68d3SGreg Clayton Entry entry; 2113b9c1b51eSKate Stone if (!variable_format.empty()) { 21143a29f8b9SPavel Labath entry.printf_format = variable_format.str(); 2115554f68d3SGreg Clayton 2116554f68d3SGreg Clayton // If the format contains a '%' we are going to assume this is 2117554f68d3SGreg Clayton // a printf style format. So if you want to format your thread ID 2118554f68d3SGreg Clayton // using "0x%llx" you can use: 2119554f68d3SGreg Clayton // ${thread.id%0x%llx} 2120554f68d3SGreg Clayton // 2121554f68d3SGreg Clayton // If there is no '%' in the format, then it is assumed to be a 2122554f68d3SGreg Clayton // LLDB format name, or one of the extended formats specified in 2123554f68d3SGreg Clayton // the switch statement below. 2124554f68d3SGreg Clayton 2125b9c1b51eSKate Stone if (entry.printf_format.find('%') == std::string::npos) { 2126554f68d3SGreg Clayton bool clear_printf = false; 2127554f68d3SGreg Clayton 2128b9c1b51eSKate Stone if (FormatManager::GetFormatFromCString( 2129b9c1b51eSKate Stone entry.printf_format.c_str(), false, entry.fmt)) { 2130554f68d3SGreg Clayton // We have an LLDB format, so clear the printf format 2131554f68d3SGreg Clayton clear_printf = true; 2132b9c1b51eSKate Stone } else if (entry.printf_format.size() == 1) { 2133b9c1b51eSKate Stone switch (entry.printf_format[0]) { 2134554f68d3SGreg Clayton case '@': // if this is an @ sign, print ObjC description 2135b9c1b51eSKate Stone entry.number = ValueObject:: 2136b9c1b51eSKate Stone eValueObjectRepresentationStyleLanguageSpecific; 2137554f68d3SGreg Clayton clear_printf = true; 2138554f68d3SGreg Clayton break; 2139b9c1b51eSKate Stone case 'V': // if this is a V, print the value using the default 2140b9c1b51eSKate Stone // format 2141b9c1b51eSKate Stone entry.number = 2142b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2143554f68d3SGreg Clayton clear_printf = true; 2144554f68d3SGreg Clayton break; 2145554f68d3SGreg Clayton case 'L': // if this is an L, print the location of the value 2146b9c1b51eSKate Stone entry.number = 2147b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleLocation; 2148554f68d3SGreg Clayton clear_printf = true; 2149554f68d3SGreg Clayton break; 2150554f68d3SGreg Clayton case 'S': // if this is an S, print the summary after all 2151b9c1b51eSKate Stone entry.number = 2152b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2153554f68d3SGreg Clayton clear_printf = true; 2154554f68d3SGreg Clayton break; 2155554f68d3SGreg Clayton case '#': // if this is a '#', print the number of children 2156b9c1b51eSKate Stone entry.number = 2157b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleChildrenCount; 2158554f68d3SGreg Clayton clear_printf = true; 2159554f68d3SGreg Clayton break; 2160554f68d3SGreg Clayton case 'T': // if this is a 'T', print the type 2161b9c1b51eSKate Stone entry.number = 2162b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleType; 2163554f68d3SGreg Clayton clear_printf = true; 2164554f68d3SGreg Clayton break; 2165554f68d3SGreg Clayton case 'N': // if this is a 'N', print the name 2166b9c1b51eSKate Stone entry.number = 2167b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleName; 2168554f68d3SGreg Clayton clear_printf = true; 2169554f68d3SGreg Clayton break; 2170281b65bcSGreg Clayton case '>': // if this is a '>', print the expression path 2171b9c1b51eSKate Stone entry.number = ValueObject:: 2172b9c1b51eSKate Stone eValueObjectRepresentationStyleExpressionPath; 2173554f68d3SGreg Clayton clear_printf = true; 2174554f68d3SGreg Clayton break; 2175554f68d3SGreg Clayton default: 2176b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2177b9c1b51eSKate Stone entry.printf_format.c_str()); 2178554f68d3SGreg Clayton return error; 2179554f68d3SGreg Clayton } 2180b9c1b51eSKate Stone } else if (FormatManager::GetFormatFromCString( 2181b9c1b51eSKate Stone entry.printf_format.c_str(), true, entry.fmt)) { 2182554f68d3SGreg Clayton clear_printf = true; 2183b9c1b51eSKate Stone } else if (entry.printf_format == "tid") { 2184554f68d3SGreg Clayton verify_is_thread_id = true; 2185b9c1b51eSKate Stone } else { 2186b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2187b9c1b51eSKate Stone entry.printf_format.c_str()); 2188554f68d3SGreg Clayton return error; 2189554f68d3SGreg Clayton } 2190554f68d3SGreg Clayton 2191554f68d3SGreg Clayton // Our format string turned out to not be a printf style format 2192554f68d3SGreg Clayton // so lets clear the string 2193554f68d3SGreg Clayton if (clear_printf) 2194554f68d3SGreg Clayton entry.printf_format.clear(); 2195554f68d3SGreg Clayton } 2196554f68d3SGreg Clayton } 2197554f68d3SGreg Clayton 2198554f68d3SGreg Clayton // Check for dereferences 2199b9c1b51eSKate Stone if (variable[0] == '*') { 2200554f68d3SGreg Clayton entry.deref = true; 2201554f68d3SGreg Clayton variable = variable.drop_front(); 2202554f68d3SGreg Clayton } 2203554f68d3SGreg Clayton 2204554f68d3SGreg Clayton error = ParseEntry(variable, &g_root, entry); 2205554f68d3SGreg Clayton if (error.Fail()) 2206554f68d3SGreg Clayton return error; 2207554f68d3SGreg Clayton 2208b9c1b51eSKate Stone if (verify_is_thread_id) { 2209554f68d3SGreg Clayton if (entry.type != Entry::Type::ThreadID && 2210b9c1b51eSKate Stone entry.type != Entry::Type::ThreadProtocolID) { 2211b9c1b51eSKate Stone error.SetErrorString("the 'tid' format can only be used on " 2212b9c1b51eSKate Stone "${thread.id} and ${thread.protocol_id}"); 2213554f68d3SGreg Clayton } 2214554f68d3SGreg Clayton } 2215554f68d3SGreg Clayton 2216b9c1b51eSKate Stone switch (entry.type) { 2217554f68d3SGreg Clayton case Entry::Type::Variable: 2218554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 2219b9c1b51eSKate Stone if (entry.number == 0) { 2220554f68d3SGreg Clayton if (entry.string.empty()) 2221b9c1b51eSKate Stone entry.number = 2222b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2223554f68d3SGreg Clayton else 2224b9c1b51eSKate Stone entry.number = 2225b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2226554f68d3SGreg Clayton } 2227554f68d3SGreg Clayton break; 2228554f68d3SGreg Clayton default: 2229b9c1b51eSKate Stone // Make sure someone didn't try to dereference anything but ${var} 2230b9c1b51eSKate Stone // or ${svar} 2231b9c1b51eSKate Stone if (entry.deref) { 2232b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2233b9c1b51eSKate Stone "${%s} can't be dereferenced, only ${var} and ${svar} can.", 2234b9c1b51eSKate Stone variable.str().c_str()); 2235554f68d3SGreg Clayton return error; 2236554f68d3SGreg Clayton } 2237554f68d3SGreg Clayton } 2238554f68d3SGreg Clayton // Check if this entry just wants to insert a constant string 2239554f68d3SGreg Clayton // value into the parent_entry, if so, insert the string with 2240554f68d3SGreg Clayton // AppendText, else append the entry to the parent_entry. 2241554f68d3SGreg Clayton if (entry.type == Entry::Type::InsertString) 2242554f68d3SGreg Clayton parent_entry.AppendText(entry.string.c_str()); 2243554f68d3SGreg Clayton else 2244554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(entry)); 2245554f68d3SGreg Clayton } 2246554f68d3SGreg Clayton } 2247554f68d3SGreg Clayton break; 2248554f68d3SGreg Clayton } 2249554f68d3SGreg Clayton } 2250554f68d3SGreg Clayton return error; 2251554f68d3SGreg Clayton } 2252554f68d3SGreg Clayton 2253b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, 2254b9c1b51eSKate Stone llvm::StringRef &variable_name, 2255b9c1b51eSKate Stone llvm::StringRef &variable_format) { 2256554f68d3SGreg Clayton Error error; 2257554f68d3SGreg Clayton variable_name = llvm::StringRef(); 2258554f68d3SGreg Clayton variable_format = llvm::StringRef(); 2259554f68d3SGreg Clayton 2260e8433cc1SBruce Mitchener const size_t paren_pos = format_str.find('}'); 2261b9c1b51eSKate Stone if (paren_pos != llvm::StringRef::npos) { 2262e8433cc1SBruce Mitchener const size_t percent_pos = format_str.find('%'); 2263b9c1b51eSKate Stone if (percent_pos < paren_pos) { 2264b9c1b51eSKate Stone if (percent_pos > 0) { 2265554f68d3SGreg Clayton if (percent_pos > 1) 2266554f68d3SGreg Clayton variable_name = format_str.substr(0, percent_pos); 2267b9c1b51eSKate Stone variable_format = 2268b9c1b51eSKate Stone format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2269554f68d3SGreg Clayton } 2270b9c1b51eSKate Stone } else { 2271554f68d3SGreg Clayton variable_name = format_str.substr(0, paren_pos); 2272554f68d3SGreg Clayton } 2273554f68d3SGreg Clayton // Strip off elements and the formatting and the trailing '}' 2274554f68d3SGreg Clayton format_str = format_str.substr(paren_pos + 1); 2275b9c1b51eSKate Stone } else { 2276b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2277b9c1b51eSKate Stone "missing terminating '}' character for '${%s'", 2278b9c1b51eSKate Stone format_str.str().c_str()); 2279554f68d3SGreg Clayton } 2280554f68d3SGreg Clayton return error; 2281554f68d3SGreg Clayton } 2282554f68d3SGreg Clayton 2283b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, 2284b9c1b51eSKate Stone llvm::StringRef variable_name, 2285b9c1b51eSKate Stone llvm::StringRef variable_format) { 2286b9c1b51eSKate Stone if (variable_name.empty() || variable_name.equals(".fullpath")) { 2287554f68d3SGreg Clayton file_spec.Dump(&s); 2288554f68d3SGreg Clayton return true; 2289b9c1b51eSKate Stone } else if (variable_name.equals(".basename")) { 2290554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2291554f68d3SGreg Clayton return true; 2292b9c1b51eSKate Stone } else if (variable_name.equals(".dirname")) { 2293554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2294554f68d3SGreg Clayton return true; 2295554f68d3SGreg Clayton } 2296554f68d3SGreg Clayton return false; 2297554f68d3SGreg Clayton } 2298554f68d3SGreg Clayton 2299b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix, 2300b9c1b51eSKate Stone const char *suffix) { 2301554f68d3SGreg Clayton std::string match(prefix.str()); 2302554f68d3SGreg Clayton match.append(suffix); 23033a29f8b9SPavel Labath return match; 2304554f68d3SGreg Clayton } 2305554f68d3SGreg Clayton 2306b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def, 2307554f68d3SGreg Clayton const llvm::StringRef &prefix, 2308554f68d3SGreg Clayton const llvm::StringRef &match_prefix, 2309b9c1b51eSKate Stone StringList &matches) { 2310554f68d3SGreg Clayton const size_t n = def->num_children; 2311b9c1b51eSKate Stone if (n > 0) { 2312b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 23133a29f8b9SPavel Labath std::string match = prefix.str(); 2314554f68d3SGreg Clayton if (match_prefix.empty()) 2315554f68d3SGreg Clayton matches.AppendString(MakeMatch(prefix, def->children[i].name)); 2316b9c1b51eSKate Stone else if (strncmp(def->children[i].name, match_prefix.data(), 2317b9c1b51eSKate Stone match_prefix.size()) == 0) 2318b9c1b51eSKate Stone matches.AppendString( 2319b9c1b51eSKate Stone MakeMatch(prefix, def->children[i].name + match_prefix.size())); 2320554f68d3SGreg Clayton } 2321554f68d3SGreg Clayton } 2322554f68d3SGreg Clayton } 2323a74f37a5SEugene Zelenko 23244aa8753cSZachary Turner size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, 2325b9c1b51eSKate Stone int max_return_elements, bool &word_complete, 2326b9c1b51eSKate Stone StringList &matches) { 2327554f68d3SGreg Clayton word_complete = false; 23284aa8753cSZachary Turner str = str.drop_front(match_start_point); 2329554f68d3SGreg Clayton matches.Clear(); 2330554f68d3SGreg Clayton 2331554f68d3SGreg Clayton const size_t dollar_pos = str.rfind('$'); 23324aa8753cSZachary Turner if (dollar_pos == llvm::StringRef::npos) 23334aa8753cSZachary Turner return 0; 23344aa8753cSZachary Turner 2335554f68d3SGreg Clayton // Hitting TAB after $ at the end of the string add a "{" 2336b9c1b51eSKate Stone if (dollar_pos == str.size() - 1) { 23373a29f8b9SPavel Labath std::string match = str.str(); 2338554f68d3SGreg Clayton match.append("{"); 23394aa8753cSZachary Turner matches.AppendString(match); 23404aa8753cSZachary Turner return 1; 23414aa8753cSZachary Turner } 23424aa8753cSZachary Turner 23434aa8753cSZachary Turner if (str[dollar_pos + 1] != '{') 23444aa8753cSZachary Turner return 0; 23454aa8753cSZachary Turner 2346554f68d3SGreg Clayton const size_t close_pos = str.find('}', dollar_pos + 2); 23474aa8753cSZachary Turner if (close_pos != llvm::StringRef::npos) 23484aa8753cSZachary Turner return 0; 23494aa8753cSZachary Turner 2350554f68d3SGreg Clayton const size_t format_pos = str.find('%', dollar_pos + 2); 23514aa8753cSZachary Turner if (format_pos != llvm::StringRef::npos) 23524aa8753cSZachary Turner return 0; 23534aa8753cSZachary Turner 2354554f68d3SGreg Clayton llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); 2355b9c1b51eSKate Stone if (partial_variable.empty()) { 2356554f68d3SGreg Clayton // Suggest all top level entites as we are just past "${" 2357554f68d3SGreg Clayton AddMatches(&g_root, str, llvm::StringRef(), matches); 23584aa8753cSZachary Turner return matches.GetSize(); 23594aa8753cSZachary Turner } 23604aa8753cSZachary Turner 2361554f68d3SGreg Clayton // We have a partially specified variable, find it 2362554f68d3SGreg Clayton llvm::StringRef remainder; 2363b9c1b51eSKate Stone const FormatEntity::Entry::Definition *entry_def = 2364b9c1b51eSKate Stone FindEntry(partial_variable, &g_root, remainder); 23654aa8753cSZachary Turner if (!entry_def) 23664aa8753cSZachary Turner return 0; 23674aa8753cSZachary Turner 2368554f68d3SGreg Clayton const size_t n = entry_def->num_children; 2369554f68d3SGreg Clayton 2370b9c1b51eSKate Stone if (remainder.empty()) { 2371554f68d3SGreg Clayton // Exact match 2372b9c1b51eSKate Stone if (n > 0) { 2373554f68d3SGreg Clayton // "${thread.info" <TAB> 23743a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, ".")); 2375b9c1b51eSKate Stone } else { 2376554f68d3SGreg Clayton // "${thread.id" <TAB> 23773a29f8b9SPavel Labath matches.AppendString(MakeMatch(str, "}")); 2378554f68d3SGreg Clayton word_complete = true; 2379554f68d3SGreg Clayton } 2380b9c1b51eSKate Stone } else if (remainder.equals(".")) { 2381554f68d3SGreg Clayton // "${thread." <TAB> 2382554f68d3SGreg Clayton AddMatches(entry_def, str, llvm::StringRef(), matches); 2383b9c1b51eSKate Stone } else { 2384554f68d3SGreg Clayton // We have a partial match 2385554f68d3SGreg Clayton // "${thre" <TAB> 2386554f68d3SGreg Clayton AddMatches(entry_def, str, remainder, matches); 2387554f68d3SGreg Clayton } 2388554f68d3SGreg Clayton return matches.GetSize(); 2389554f68d3SGreg Clayton } 2390