1554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===// 2554f68d3SGreg Clayton // 3554f68d3SGreg Clayton // The LLVM Compiler Infrastructure 4554f68d3SGreg Clayton // 5554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source 6554f68d3SGreg Clayton // License. See LICENSE.TXT for details. 7554f68d3SGreg Clayton // 8554f68d3SGreg Clayton //===----------------------------------------------------------------------===// 9554f68d3SGreg Clayton 10554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 11554f68d3SGreg Clayton 12554f68d3SGreg Clayton #include "lldb/Core/Address.h" 132f3df613SZachary Turner #include "lldb/Core/AddressRange.h" // for AddressRange 14554f68d3SGreg Clayton #include "lldb/Core/Debugger.h" 15554f68d3SGreg Clayton #include "lldb/Core/Module.h" 162f3df613SZachary Turner #include "lldb/Core/RegisterValue.h" // for RegisterValue 17554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h" 18554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 19554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h" 202f3df613SZachary Turner #include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier... 21554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h" 222f3df613SZachary Turner #include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::... 23937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h" 24554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 25554f68d3SGreg Clayton #include "lldb/Symbol/Block.h" 26554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 272f3df613SZachary Turner #include "lldb/Symbol/CompilerType.h" // for CompilerType 28554f68d3SGreg Clayton #include "lldb/Symbol/Function.h" 29554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h" 30554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h" 312f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext 32554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h" 33554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h" 342f3df613SZachary Turner #include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS... 350e0984eeSJim Ingham #include "lldb/Target/Language.h" 36554f68d3SGreg Clayton #include "lldb/Target/Process.h" 37554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h" 38554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h" 39554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h" 40554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h" 41554f68d3SGreg Clayton #include "lldb/Target/Target.h" 42554f68d3SGreg Clayton #include "lldb/Target/Thread.h" 43554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 445f19b907SPavel Labath #include "lldb/Utility/ArchSpec.h" // for ArchSpec 452f3df613SZachary Turner #include "lldb/Utility/ConstString.h" // for ConstString, oper... 465713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 472f3df613SZachary Turner #include "lldb/Utility/Log.h" // for Log 482f3df613SZachary Turner #include "lldb/Utility/Logging.h" // for GetLogIfAllCatego... 492f3df613SZachary Turner #include "lldb/Utility/SharingPtr.h" // for SharingPtr 50bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 51bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 522f3df613SZachary Turner #include "lldb/Utility/StringList.h" // for StringList 53f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" // for StructuredData::O... 542f3df613SZachary Turner #include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS 552f3df613SZachary Turner #include "lldb/lldb-forward.h" // for ValueObjectSP 562f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" 572f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 582f3df613SZachary Turner #include "llvm/ADT/Triple.h" // for Triple, Triple::O... 592f3df613SZachary Turner #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH 602f3df613SZachary Turner 612f3df613SZachary Turner #include <ctype.h> // for isxdigit 622f3df613SZachary Turner #include <inttypes.h> // for PRIu64, PRIx64 632f3df613SZachary Turner #include <memory> // for shared_ptr, opera... 642f3df613SZachary Turner #include <stdio.h> // for sprintf 652f3df613SZachary Turner #include <stdlib.h> // for strtoul 662f3df613SZachary Turner #include <string.h> // for size_t, strchr 672f3df613SZachary Turner #include <type_traits> // for move 682f3df613SZachary Turner #include <utility> // for pair 692f3df613SZachary Turner 702f3df613SZachary Turner namespace lldb_private { 712f3df613SZachary Turner class ScriptInterpreter; 722f3df613SZachary Turner } 732f3df613SZachary Turner namespace lldb_private { 742f3df613SZachary Turner struct RegisterInfo; 752f3df613SZachary Turner } 76554f68d3SGreg Clayton 77554f68d3SGreg Clayton using namespace lldb; 78554f68d3SGreg Clayton using namespace lldb_private; 79554f68d3SGreg Clayton 80b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath }; 81554f68d3SGreg Clayton 82b9c1b51eSKate Stone #define ENTRY(n, t, f) \ 83b9c1b51eSKate Stone { \ 84b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 85b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false \ 86b9c1b51eSKate Stone } 87b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v) \ 88b9c1b51eSKate Stone { \ 89b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 90b9c1b51eSKate Stone FormatEntity::Entry::FormatType::f, v, 0, nullptr, false \ 91b9c1b51eSKate Stone } 92b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c) \ 93b9c1b51eSKate Stone { \ 94b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 95e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 96e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \ 97b9c1b51eSKate Stone } 98b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \ 99b9c1b51eSKate Stone { \ 100b9c1b51eSKate Stone n, nullptr, FormatEntity::Entry::Type::t, \ 101e28558f0SZachary Turner FormatEntity::Entry::FormatType::f, 0, \ 102e28558f0SZachary Turner static_cast<uint32_t>(llvm::array_lengthof(c)), c, true \ 103b9c1b51eSKate Stone } 104b9c1b51eSKate Stone #define ENTRY_STRING(n, s) \ 105b9c1b51eSKate Stone { \ 106b9c1b51eSKate Stone n, s, FormatEntity::Entry::Type::InsertString, \ 107b9c1b51eSKate Stone FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false \ 108b9c1b51eSKate Stone } 109b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = { 110b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 111554f68d3SGreg Clayton 112b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = { 113b9c1b51eSKate Stone ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64), 114554f68d3SGreg Clayton ENTRY("load", AddressLoadOrFile, UInt64), 115554f68d3SGreg Clayton }; 116554f68d3SGreg Clayton 117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = { 118554f68d3SGreg Clayton ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), 119554f68d3SGreg Clayton ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), 120b9c1b51eSKate Stone ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)}; 121554f68d3SGreg Clayton 122b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = { 123554f68d3SGreg Clayton ENTRY("index", FrameIndex, UInt32), 124554f68d3SGreg Clayton ENTRY("pc", FrameRegisterPC, UInt64), 125554f68d3SGreg Clayton ENTRY("fp", FrameRegisterFP, UInt64), 126554f68d3SGreg Clayton ENTRY("sp", FrameRegisterSP, UInt64), 127554f68d3SGreg Clayton ENTRY("flags", FrameRegisterFlags, UInt64), 1286a9767c7SJim Ingham ENTRY("no-debug", FrameNoDebug, None), 129554f68d3SGreg Clayton ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), 130554f68d3SGreg Clayton }; 131554f68d3SGreg Clayton 132b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = { 133b9c1b51eSKate Stone ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString), 134554f68d3SGreg Clayton ENTRY("name-without-args", FunctionNameNoArgs, CString), 135554f68d3SGreg Clayton ENTRY("name-with-args", FunctionNameWithArgs, CString), 136554f68d3SGreg Clayton ENTRY("addr-offset", FunctionAddrOffset, UInt64), 137b9c1b51eSKate Stone ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, 138b9c1b51eSKate Stone UInt64), 139554f68d3SGreg Clayton ENTRY("line-offset", FunctionLineOffset, UInt64), 140c980fa92SJason Molenda ENTRY("pc-offset", FunctionPCOffset, UInt64), 141c980fa92SJason Molenda ENTRY("initial-function", FunctionInitial, None), 1426ab659a9SJason Molenda ENTRY("changed", FunctionChanged, None), 143b9c1b51eSKate Stone ENTRY("is-optimized", FunctionIsOptimized, None)}; 144554f68d3SGreg Clayton 145b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = { 146554f68d3SGreg Clayton ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), 147554f68d3SGreg Clayton ENTRY("number", LineEntryLineNumber, UInt32), 148554f68d3SGreg Clayton ENTRY("start-addr", LineEntryStartAddress, UInt64), 149554f68d3SGreg Clayton ENTRY("end-addr", LineEntryEndAddress, UInt64), 150554f68d3SGreg Clayton }; 151554f68d3SGreg Clayton 152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = { 153554f68d3SGreg Clayton ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), 154554f68d3SGreg Clayton }; 155554f68d3SGreg Clayton 156b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = { 157554f68d3SGreg Clayton ENTRY("id", ProcessID, UInt64), 158554f68d3SGreg Clayton ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename), 159554f68d3SGreg Clayton ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries), 160554f68d3SGreg Clayton }; 161554f68d3SGreg Clayton 162b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = { 163b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 164554f68d3SGreg Clayton 165b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = { 166b9c1b51eSKate Stone ENTRY("*", ParentString, None)}; 167554f68d3SGreg Clayton 168b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = { 169554f68d3SGreg Clayton ENTRY("id", ThreadID, UInt64), 170554f68d3SGreg Clayton ENTRY("protocol_id", ThreadProtocolID, UInt64), 171554f68d3SGreg Clayton ENTRY("index", ThreadIndexID, UInt32), 172554f68d3SGreg Clayton ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry), 173554f68d3SGreg Clayton ENTRY("queue", ThreadQueue, CString), 174554f68d3SGreg Clayton ENTRY("name", ThreadName, CString), 175554f68d3SGreg Clayton ENTRY("stop-reason", ThreadStopReason, CString), 176554f68d3SGreg Clayton ENTRY("return-value", ThreadReturnValue, CString), 177554f68d3SGreg Clayton ENTRY("completed-expression", ThreadCompletedExpression, CString), 178554f68d3SGreg Clayton }; 179554f68d3SGreg Clayton 180b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = { 181554f68d3SGreg Clayton ENTRY("arch", TargetArch, CString), 182554f68d3SGreg Clayton }; 183554f68d3SGreg Clayton 184554f68d3SGreg Clayton #define _TO_STR2(_val) #_val 185554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val) 186554f68d3SGreg Clayton 187b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { 188b9c1b51eSKate Stone ENTRY_STRING("black", 189b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 190554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 191b9c1b51eSKate Stone ENTRY_STRING("green", 192b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 193b9c1b51eSKate Stone ENTRY_STRING("yellow", 194b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 195b9c1b51eSKate Stone ENTRY_STRING("blue", 196b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 197b9c1b51eSKate Stone ENTRY_STRING("purple", 198b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 199b9c1b51eSKate Stone ENTRY_STRING("cyan", 200b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 201b9c1b51eSKate Stone ENTRY_STRING("white", 202b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 203554f68d3SGreg Clayton }; 204554f68d3SGreg Clayton 205b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { 206b9c1b51eSKate Stone ENTRY_STRING("black", 207b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 208554f68d3SGreg Clayton ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 209b9c1b51eSKate Stone ENTRY_STRING("green", 210b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 211b9c1b51eSKate Stone ENTRY_STRING("yellow", 212b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 213b9c1b51eSKate Stone ENTRY_STRING("blue", 214b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 215b9c1b51eSKate Stone ENTRY_STRING("purple", 216b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 217b9c1b51eSKate Stone ENTRY_STRING("cyan", 218b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 219b9c1b51eSKate Stone ENTRY_STRING("white", 220b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 221554f68d3SGreg Clayton }; 222554f68d3SGreg Clayton 223b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = { 224554f68d3SGreg Clayton ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries), 225554f68d3SGreg Clayton ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries), 226b9c1b51eSKate Stone ENTRY_STRING("normal", 227b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 228554f68d3SGreg Clayton ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 229554f68d3SGreg Clayton ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 230b9c1b51eSKate Stone ENTRY_STRING("italic", 231b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 232b9c1b51eSKate Stone ENTRY_STRING("underline", 233b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 234b9c1b51eSKate Stone ENTRY_STRING("slow-blink", 235b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 236b9c1b51eSKate Stone ENTRY_STRING("fast-blink", 237b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 238b9c1b51eSKate Stone ENTRY_STRING("negative", 239b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 240b9c1b51eSKate Stone ENTRY_STRING("conceal", 241b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 242b9c1b51eSKate Stone ENTRY_STRING("crossed-out", 243b9c1b51eSKate Stone ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 244554f68d3SGreg Clayton }; 245554f68d3SGreg Clayton 246b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = { 247554f68d3SGreg Clayton ENTRY("frame", ScriptFrame, None), 248554f68d3SGreg Clayton ENTRY("process", ScriptProcess, None), 249554f68d3SGreg Clayton ENTRY("target", ScriptTarget, None), 250554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 251554f68d3SGreg Clayton ENTRY("var", ScriptVariable, None), 252554f68d3SGreg Clayton ENTRY("svar", ScriptVariableSynthetic, None), 253554f68d3SGreg Clayton ENTRY("thread", ScriptThread, None), 254554f68d3SGreg Clayton }; 255554f68d3SGreg Clayton 256b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = { 257554f68d3SGreg Clayton ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries), 258554f68d3SGreg Clayton ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64), 259554f68d3SGreg Clayton ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries), 260554f68d3SGreg Clayton ENTRY("current-pc-arrow", CurrentPCArrow, CString), 261554f68d3SGreg Clayton ENTRY_CHILDREN("file", File, CString, g_file_child_entries), 262dc975670SDawn Perchik ENTRY("language", Lang, CString), 263554f68d3SGreg Clayton ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries), 264554f68d3SGreg Clayton ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries), 265554f68d3SGreg Clayton ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries), 266554f68d3SGreg Clayton ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries), 267554f68d3SGreg Clayton ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries), 268554f68d3SGreg Clayton ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries), 269b9c1b51eSKate Stone ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None, 270b9c1b51eSKate Stone g_svar_child_entries), 271554f68d3SGreg Clayton ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries), 272554f68d3SGreg Clayton ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries), 273554f68d3SGreg Clayton ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries), 274554f68d3SGreg Clayton }; 275554f68d3SGreg Clayton 276b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root = 277b9c1b51eSKate Stone ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries); 278554f68d3SGreg Clayton 279b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s) 280b9c1b51eSKate Stone : string(s.data(), s.size()), printf_format(), children(), 281b9c1b51eSKate Stone definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), 282b9c1b51eSKate Stone number(0), deref(false) {} 283554f68d3SGreg Clayton 284b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch) 285b9c1b51eSKate Stone : string(1, ch), printf_format(), children(), definition(nullptr), 286b9c1b51eSKate Stone type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} 287554f68d3SGreg Clayton 288b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) { 289554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 290554f68d3SGreg Clayton children.push_back(Entry(ch)); 291554f68d3SGreg Clayton else 292554f68d3SGreg Clayton children.back().string.append(1, ch); 293554f68d3SGreg Clayton } 294554f68d3SGreg Clayton 295b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { 296554f68d3SGreg Clayton if (children.empty() || children.back().type != Entry::Type::String) 297554f68d3SGreg Clayton children.push_back(Entry(s)); 298554f68d3SGreg Clayton else 299554f68d3SGreg Clayton children.back().string.append(s.data(), s.size()); 300554f68d3SGreg Clayton } 301554f68d3SGreg Clayton 302b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) { 303554f68d3SGreg Clayton return AppendText(llvm::StringRef(cstr)); 304554f68d3SGreg Clayton } 305554f68d3SGreg Clayton 30697206d57SZachary Turner Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { 307554f68d3SGreg Clayton entry.Clear(); 308554f68d3SGreg Clayton entry.type = Entry::Type::Root; 309554f68d3SGreg Clayton llvm::StringRef modifiable_format(format_str); 310554f68d3SGreg Clayton return ParseInternal(modifiable_format, entry, 0); 311554f68d3SGreg Clayton } 312554f68d3SGreg Clayton 313b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee) \ 314b9c1b51eSKate Stone case FormatEntity::Entry::Type::eee: \ 315b9c1b51eSKate Stone return #eee 316554f68d3SGreg Clayton 317b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) { 318b9c1b51eSKate Stone switch (t) { 319554f68d3SGreg Clayton ENUM_TO_CSTR(Invalid); 320554f68d3SGreg Clayton ENUM_TO_CSTR(ParentNumber); 321554f68d3SGreg Clayton ENUM_TO_CSTR(ParentString); 322554f68d3SGreg Clayton ENUM_TO_CSTR(InsertString); 323554f68d3SGreg Clayton ENUM_TO_CSTR(Root); 324554f68d3SGreg Clayton ENUM_TO_CSTR(String); 325554f68d3SGreg Clayton ENUM_TO_CSTR(Scope); 326554f68d3SGreg Clayton ENUM_TO_CSTR(Variable); 327554f68d3SGreg Clayton ENUM_TO_CSTR(VariableSynthetic); 328554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariable); 329554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptVariableSynthetic); 330554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoad); 331554f68d3SGreg Clayton ENUM_TO_CSTR(AddressFile); 332554f68d3SGreg Clayton ENUM_TO_CSTR(AddressLoadOrFile); 333554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessID); 334554f68d3SGreg Clayton ENUM_TO_CSTR(ProcessFile); 335554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptProcess); 336554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadID); 337554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadProtocolID); 338554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadIndexID); 339554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadName); 340554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadQueue); 341554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadStopReason); 342554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadReturnValue); 343554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadCompletedExpression); 344554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptThread); 345554f68d3SGreg Clayton ENUM_TO_CSTR(ThreadInfo); 346554f68d3SGreg Clayton ENUM_TO_CSTR(TargetArch); 347554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptTarget); 348554f68d3SGreg Clayton ENUM_TO_CSTR(ModuleFile); 349554f68d3SGreg Clayton ENUM_TO_CSTR(File); 350dc975670SDawn Perchik ENUM_TO_CSTR(Lang); 351554f68d3SGreg Clayton ENUM_TO_CSTR(FrameIndex); 3526a9767c7SJim Ingham ENUM_TO_CSTR(FrameNoDebug); 353554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterPC); 354554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterSP); 355554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFP); 356554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterFlags); 357554f68d3SGreg Clayton ENUM_TO_CSTR(FrameRegisterByName); 358554f68d3SGreg Clayton ENUM_TO_CSTR(ScriptFrame); 359554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionID); 360554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionDidChange); 361554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionInitialFunction); 362554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionName); 363554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameWithArgs); 364554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionNameNoArgs); 365554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffset); 366554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 367554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionLineOffset); 368554f68d3SGreg Clayton ENUM_TO_CSTR(FunctionPCOffset); 369c980fa92SJason Molenda ENUM_TO_CSTR(FunctionInitial); 370c980fa92SJason Molenda ENUM_TO_CSTR(FunctionChanged); 3716ab659a9SJason Molenda ENUM_TO_CSTR(FunctionIsOptimized); 372554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryFile); 373554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryLineNumber); 374554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryStartAddress); 375554f68d3SGreg Clayton ENUM_TO_CSTR(LineEntryEndAddress); 376554f68d3SGreg Clayton ENUM_TO_CSTR(CurrentPCArrow); 377554f68d3SGreg Clayton } 378554f68d3SGreg Clayton return "???"; 379554f68d3SGreg Clayton } 380554f68d3SGreg Clayton 381554f68d3SGreg Clayton #undef ENUM_TO_CSTR 382554f68d3SGreg Clayton 383b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const { 384554f68d3SGreg Clayton s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 385554f68d3SGreg Clayton if (fmt != eFormatDefault) 386554f68d3SGreg Clayton s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); 387554f68d3SGreg Clayton if (!string.empty()) 388554f68d3SGreg Clayton s.Printf("string = \"%s\"", string.c_str()); 389554f68d3SGreg Clayton if (!printf_format.empty()) 390554f68d3SGreg Clayton s.Printf("printf_format = \"%s\"", printf_format.c_str()); 391554f68d3SGreg Clayton if (number != 0) 392554f68d3SGreg Clayton s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 393554f68d3SGreg Clayton if (deref) 394554f68d3SGreg Clayton s.Printf("deref = true, "); 395554f68d3SGreg Clayton s.EOL(); 396b9c1b51eSKate Stone for (const auto &child : children) { 397554f68d3SGreg Clayton child.Dump(s, depth + 1); 398554f68d3SGreg Clayton } 399554f68d3SGreg Clayton } 400554f68d3SGreg Clayton 401554f68d3SGreg Clayton template <typename T> 402b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, 403b9c1b51eSKate Stone const ExecutionContext *exe_ctx, T t, 404b9c1b51eSKate Stone const char *script_function_name) { 405554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 406554f68d3SGreg Clayton 407b9c1b51eSKate Stone if (target) { 408b9c1b51eSKate Stone ScriptInterpreter *script_interpreter = 409b9c1b51eSKate Stone target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 410b9c1b51eSKate Stone if (script_interpreter) { 41197206d57SZachary Turner Status error; 412554f68d3SGreg Clayton std::string script_output; 413554f68d3SGreg Clayton 414b9c1b51eSKate Stone if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, 415b9c1b51eSKate Stone script_output, error) && 416b9c1b51eSKate Stone error.Success()) { 417554f68d3SGreg Clayton s.Printf("%s", script_output.c_str()); 418554f68d3SGreg Clayton return true; 419b9c1b51eSKate Stone } else { 420554f68d3SGreg Clayton s.Printf("<error: %s>", error.AsCString()); 421554f68d3SGreg Clayton } 422554f68d3SGreg Clayton } 423554f68d3SGreg Clayton } 424554f68d3SGreg Clayton return false; 425554f68d3SGreg Clayton } 426554f68d3SGreg Clayton 427b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc, 428b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address &addr, 429b9c1b51eSKate Stone bool print_file_addr_or_load_addr) { 430554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 431554f68d3SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 432554f68d3SGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 433554f68d3SGreg Clayton vaddr = addr.GetLoadAddress(target); 434554f68d3SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 435554f68d3SGreg Clayton vaddr = addr.GetFileAddress(); 436554f68d3SGreg Clayton 437b9c1b51eSKate Stone if (vaddr != LLDB_INVALID_ADDRESS) { 438554f68d3SGreg Clayton int addr_width = 0; 439b9c1b51eSKate Stone if (exe_ctx && target) { 440554f68d3SGreg Clayton addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 441554f68d3SGreg Clayton } 442554f68d3SGreg Clayton if (addr_width == 0) 443554f68d3SGreg Clayton addr_width = 16; 444b9c1b51eSKate Stone if (print_file_addr_or_load_addr) { 445a74f37a5SEugene Zelenko ExecutionContextScope *exe_scope = nullptr; 446554f68d3SGreg Clayton if (exe_ctx) 447554f68d3SGreg Clayton exe_scope = exe_ctx->GetBestExecutionContextScope(); 448b9c1b51eSKate Stone addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, 449b9c1b51eSKate Stone Address::DumpStyleModuleWithFileAddress, 0); 450b9c1b51eSKate Stone } else { 451554f68d3SGreg Clayton s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 452554f68d3SGreg Clayton } 453554f68d3SGreg Clayton return true; 454554f68d3SGreg Clayton } 455554f68d3SGreg Clayton return false; 456554f68d3SGreg Clayton } 457554f68d3SGreg Clayton 458b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, 459554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 460554f68d3SGreg Clayton const Address &format_addr, 461b9c1b51eSKate Stone bool concrete_only, bool no_padding, 462b9c1b51eSKate Stone bool print_zero_offsets) { 463b9c1b51eSKate Stone if (format_addr.IsValid()) { 464554f68d3SGreg Clayton Address func_addr; 465554f68d3SGreg Clayton 466b9c1b51eSKate Stone if (sc) { 467b9c1b51eSKate Stone if (sc->function) { 468554f68d3SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 469b9c1b51eSKate Stone if (sc->block && !concrete_only) { 47005097246SAdrian Prantl // Check to make sure we aren't in an inline function. If we are, use 47105097246SAdrian Prantl // the inline block range that contains "format_addr" since blocks 47205097246SAdrian Prantl // can be discontiguous. 473554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 474554f68d3SGreg Clayton AddressRange inline_range; 475b9c1b51eSKate Stone if (inline_block && 476b9c1b51eSKate Stone inline_block->GetRangeContainingAddress(format_addr, 477b9c1b51eSKate Stone inline_range)) 478554f68d3SGreg Clayton func_addr = inline_range.GetBaseAddress(); 479554f68d3SGreg Clayton } 480b9c1b51eSKate Stone } else if (sc->symbol && sc->symbol->ValueIsAddress()) 481358cf1eaSGreg Clayton func_addr = sc->symbol->GetAddressRef(); 482554f68d3SGreg Clayton } 483554f68d3SGreg Clayton 484b9c1b51eSKate Stone if (func_addr.IsValid()) { 485554f68d3SGreg Clayton const char *addr_offset_padding = no_padding ? "" : " "; 486554f68d3SGreg Clayton 487b9c1b51eSKate Stone if (func_addr.GetSection() == format_addr.GetSection()) { 488554f68d3SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 489554f68d3SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 490b9c1b51eSKate Stone if (addr_file_addr > func_file_addr || 491b9c1b51eSKate Stone (addr_file_addr == func_file_addr && print_zero_offsets)) { 492b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 493b9c1b51eSKate Stone addr_file_addr - func_file_addr); 494b9c1b51eSKate Stone } else if (addr_file_addr < func_file_addr) { 495b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 496b9c1b51eSKate Stone func_file_addr - addr_file_addr); 497c980fa92SJason Molenda } 498554f68d3SGreg Clayton return true; 499b9c1b51eSKate Stone } else { 500554f68d3SGreg Clayton Target *target = Target::GetTargetFromContexts(exe_ctx, sc); 501b9c1b51eSKate Stone if (target) { 502554f68d3SGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress(target); 503554f68d3SGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress(target); 504b9c1b51eSKate Stone if (addr_load_addr > func_load_addr || 505b9c1b51eSKate Stone (addr_load_addr == func_load_addr && print_zero_offsets)) { 506b9c1b51eSKate Stone s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, 507b9c1b51eSKate Stone addr_load_addr - func_load_addr); 508b9c1b51eSKate Stone } else if (addr_load_addr < func_load_addr) { 509b9c1b51eSKate Stone s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, 510b9c1b51eSKate Stone func_load_addr - addr_load_addr); 511c980fa92SJason Molenda } 512554f68d3SGreg Clayton return true; 513554f68d3SGreg Clayton } 514554f68d3SGreg Clayton } 515554f68d3SGreg Clayton } 516554f68d3SGreg Clayton } 517554f68d3SGreg Clayton return false; 518554f68d3SGreg Clayton } 519554f68d3SGreg Clayton 520b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath, 521554f68d3SGreg Clayton size_t &close_bracket_index, 522554f68d3SGreg Clayton const char *&var_name_final_if_array_range, 523b9c1b51eSKate Stone int64_t &index_lower, int64_t &index_higher) { 5244edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 525554f68d3SGreg Clayton close_bracket_index = llvm::StringRef::npos; 526554f68d3SGreg Clayton const size_t open_bracket_index = subpath.find('['); 527b9c1b51eSKate Stone if (open_bracket_index == llvm::StringRef::npos) { 528554f68d3SGreg Clayton if (log) 529554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 530554f68d3SGreg Clayton return false; 531554f68d3SGreg Clayton } 532554f68d3SGreg Clayton 533554f68d3SGreg Clayton close_bracket_index = subpath.find(']', open_bracket_index + 1); 534554f68d3SGreg Clayton 535b9c1b51eSKate Stone if (close_bracket_index == llvm::StringRef::npos) { 536554f68d3SGreg Clayton if (log) 537554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 538554f68d3SGreg Clayton return false; 539b9c1b51eSKate Stone } else { 540554f68d3SGreg Clayton var_name_final_if_array_range = subpath.data() + open_bracket_index; 541554f68d3SGreg Clayton 542b9c1b51eSKate Stone if (close_bracket_index - open_bracket_index == 1) { 543554f68d3SGreg Clayton if (log) 544b9c1b51eSKate Stone log->Printf( 545b9c1b51eSKate Stone "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 546554f68d3SGreg Clayton index_lower = 0; 547b9c1b51eSKate Stone } else { 548554f68d3SGreg Clayton const size_t separator_index = subpath.find('-', open_bracket_index + 1); 549554f68d3SGreg Clayton 550b9c1b51eSKate Stone if (separator_index == llvm::StringRef::npos) { 551554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 552a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 553554f68d3SGreg Clayton index_higher = index_lower; 554554f68d3SGreg Clayton if (log) 555b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 556b9c1b51eSKate Stone "] detected, high index is same", 557b9c1b51eSKate Stone index_lower); 558b9c1b51eSKate Stone } else { 559554f68d3SGreg Clayton const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 560554f68d3SGreg Clayton const char *index_higher_cstr = subpath.data() + separator_index + 1; 561a74f37a5SEugene Zelenko index_lower = ::strtoul(index_lower_cstr, nullptr, 0); 562a74f37a5SEugene Zelenko index_higher = ::strtoul(index_higher_cstr, nullptr, 0); 563554f68d3SGreg Clayton if (log) 564b9c1b51eSKate Stone log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", 565b9c1b51eSKate Stone index_lower, index_higher); 566554f68d3SGreg Clayton } 567b9c1b51eSKate Stone if (index_lower > index_higher && index_higher > 0) { 568554f68d3SGreg Clayton if (log) 569554f68d3SGreg Clayton log->Printf("[ScanBracketedRange] swapping indices"); 570554f68d3SGreg Clayton const int64_t temp = index_lower; 571554f68d3SGreg Clayton index_lower = index_higher; 572554f68d3SGreg Clayton index_higher = temp; 573554f68d3SGreg Clayton } 574554f68d3SGreg Clayton } 575554f68d3SGreg Clayton } 576554f68d3SGreg Clayton return true; 577554f68d3SGreg Clayton } 578554f68d3SGreg Clayton 579b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { 580b9c1b51eSKate Stone switch (file_kind) { 581554f68d3SGreg Clayton case FileKind::FileError: 582554f68d3SGreg Clayton break; 583554f68d3SGreg Clayton 584554f68d3SGreg Clayton case FileKind::Basename: 585b9c1b51eSKate Stone if (file.GetFilename()) { 586554f68d3SGreg Clayton s << file.GetFilename(); 587554f68d3SGreg Clayton return true; 588554f68d3SGreg Clayton } 589554f68d3SGreg Clayton break; 590554f68d3SGreg Clayton 591554f68d3SGreg Clayton case FileKind::Dirname: 592b9c1b51eSKate Stone if (file.GetDirectory()) { 593554f68d3SGreg Clayton s << file.GetDirectory(); 594554f68d3SGreg Clayton return true; 595554f68d3SGreg Clayton } 596554f68d3SGreg Clayton break; 597554f68d3SGreg Clayton 598554f68d3SGreg Clayton case FileKind::Fullpath: 599b9c1b51eSKate Stone if (file) { 600554f68d3SGreg Clayton s << file; 601554f68d3SGreg Clayton return true; 602554f68d3SGreg Clayton } 603554f68d3SGreg Clayton break; 604554f68d3SGreg Clayton } 605554f68d3SGreg Clayton return false; 606554f68d3SGreg Clayton } 607554f68d3SGreg Clayton 608b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, 609b9c1b51eSKate Stone uint32_t reg_num, Format format) 610554f68d3SGreg Clayton 611554f68d3SGreg Clayton { 612b9c1b51eSKate Stone if (frame) { 613554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 614554f68d3SGreg Clayton 615b9c1b51eSKate Stone if (reg_ctx) { 616b9c1b51eSKate Stone const uint32_t lldb_reg_num = 617b9c1b51eSKate Stone reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 618b9c1b51eSKate Stone if (lldb_reg_num != LLDB_INVALID_REGNUM) { 619b9c1b51eSKate Stone const RegisterInfo *reg_info = 620b9c1b51eSKate Stone reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); 621b9c1b51eSKate Stone if (reg_info) { 622554f68d3SGreg Clayton RegisterValue reg_value; 623b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 624554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 625554f68d3SGreg Clayton return true; 626554f68d3SGreg Clayton } 627554f68d3SGreg Clayton } 628554f68d3SGreg Clayton } 629554f68d3SGreg Clayton } 630554f68d3SGreg Clayton } 631554f68d3SGreg Clayton return false; 632554f68d3SGreg Clayton } 633554f68d3SGreg Clayton 634b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, 635554f68d3SGreg Clayton StackFrame *frame, 636b9c1b51eSKate Stone bool deref_pointer) { 6374edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 638554f68d3SGreg Clayton const char *ptr_deref_format = "[%d]"; 639554f68d3SGreg Clayton std::string ptr_deref_buffer(10, 0); 640554f68d3SGreg Clayton ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 641554f68d3SGreg Clayton if (log) 642b9c1b51eSKate Stone log->Printf("[ExpandIndexedExpression] name to deref: %s", 643b9c1b51eSKate Stone ptr_deref_buffer.c_str()); 644554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 645554f68d3SGreg Clayton ValueObject::ExpressionPathEndResultType final_value_type; 646554f68d3SGreg Clayton ValueObject::ExpressionPathScanEndReason reason_to_stop; 647b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 648b9c1b51eSKate Stone (deref_pointer ? ValueObject::eExpressionPathAftermathDereference 649b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 650b9c1b51eSKate Stone ValueObjectSP item = valobj->GetValueForExpressionPath( 651d2daca77SZachary Turner ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, 652d2daca77SZachary Turner &what_next); 653b9c1b51eSKate Stone if (!item) { 654554f68d3SGreg Clayton if (log) 655d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d," 656554f68d3SGreg Clayton " final_value_type %d", 657d2daca77SZachary Turner reason_to_stop, final_value_type); 658b9c1b51eSKate Stone } else { 659554f68d3SGreg Clayton if (log) 660d2daca77SZachary Turner log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," 661554f68d3SGreg Clayton " final_value_type %d", 662d2daca77SZachary Turner reason_to_stop, final_value_type); 663554f68d3SGreg Clayton } 664554f68d3SGreg Clayton return item; 665554f68d3SGreg Clayton } 666554f68d3SGreg Clayton 667b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar( 668b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle style) { 669b9c1b51eSKate Stone switch (style) { 670b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: 671b9c1b51eSKate Stone return '@'; 672b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleValue: 673b9c1b51eSKate Stone return 'V'; 674b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleLocation: 675b9c1b51eSKate Stone return 'L'; 676b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleSummary: 677b9c1b51eSKate Stone return 'S'; 678b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleChildrenCount: 679b9c1b51eSKate Stone return '#'; 680b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleType: 681b9c1b51eSKate Stone return 'T'; 682b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleName: 683b9c1b51eSKate Stone return 'N'; 684b9c1b51eSKate Stone case ValueObject::eValueObjectRepresentationStyleExpressionPath: 685b9c1b51eSKate Stone return '>'; 686554f68d3SGreg Clayton } 687554f68d3SGreg Clayton return '\0'; 688554f68d3SGreg Clayton } 689554f68d3SGreg Clayton 690b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc, 691554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 692b9c1b51eSKate Stone const FormatEntity::Entry &entry, ValueObject *valobj) { 693a74f37a5SEugene Zelenko if (valobj == nullptr) 694554f68d3SGreg Clayton return false; 695554f68d3SGreg Clayton 6964edfef45SEnrico Granata Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 697554f68d3SGreg Clayton Format custom_format = eFormatInvalid; 698b9c1b51eSKate Stone ValueObject::ValueObjectRepresentationStyle val_obj_display = 699b9c1b51eSKate Stone entry.string.empty() 700b9c1b51eSKate Stone ? ValueObject::eValueObjectRepresentationStyleValue 701b9c1b51eSKate Stone : ValueObject::eValueObjectRepresentationStyleSummary; 702554f68d3SGreg Clayton 703554f68d3SGreg Clayton bool do_deref_pointer = entry.deref; 704554f68d3SGreg Clayton bool is_script = false; 705b9c1b51eSKate Stone switch (entry.type) { 706554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariable: 707554f68d3SGreg Clayton is_script = true; 708554f68d3SGreg Clayton break; 709554f68d3SGreg Clayton 710554f68d3SGreg Clayton case FormatEntity::Entry::Type::Variable: 711554f68d3SGreg Clayton custom_format = entry.fmt; 712554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 713554f68d3SGreg Clayton break; 714554f68d3SGreg Clayton 715554f68d3SGreg Clayton case FormatEntity::Entry::Type::ScriptVariableSynthetic: 716554f68d3SGreg Clayton is_script = true; 71762e0681aSJason Molenda LLVM_FALLTHROUGH; 718554f68d3SGreg Clayton case FormatEntity::Entry::Type::VariableSynthetic: 719554f68d3SGreg Clayton custom_format = entry.fmt; 720554f68d3SGreg Clayton val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 721b9c1b51eSKate Stone if (!valobj->IsSynthetic()) { 722554f68d3SGreg Clayton valobj = valobj->GetSyntheticValue().get(); 723554f68d3SGreg Clayton if (valobj == nullptr) 724554f68d3SGreg Clayton return false; 725554f68d3SGreg Clayton } 726554f68d3SGreg Clayton break; 727554f68d3SGreg Clayton 728554f68d3SGreg Clayton default: 729554f68d3SGreg Clayton return false; 730554f68d3SGreg Clayton } 731554f68d3SGreg Clayton 732a74f37a5SEugene Zelenko if (valobj == nullptr) 733554f68d3SGreg Clayton return false; 734554f68d3SGreg Clayton 735b9c1b51eSKate Stone ValueObject::ExpressionPathAftermath what_next = 736b9c1b51eSKate Stone (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference 737b9c1b51eSKate Stone : ValueObject::eExpressionPathAftermathNothing); 738554f68d3SGreg Clayton ValueObject::GetValueForExpressionPathOptions options; 739b9c1b51eSKate Stone options.DontCheckDotVsArrowSyntax() 740b9c1b51eSKate Stone .DoAllowBitfieldSyntax() 741b9c1b51eSKate Stone .DoAllowFragileIVar() 742b9c1b51eSKate Stone .SetSyntheticChildrenTraversal( 743b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions:: 744b9c1b51eSKate Stone SyntheticChildrenTraversal::Both); 745a74f37a5SEugene Zelenko ValueObject *target = nullptr; 746a74f37a5SEugene Zelenko const char *var_name_final_if_array_range = nullptr; 747554f68d3SGreg Clayton size_t close_bracket_index = llvm::StringRef::npos; 748554f68d3SGreg Clayton int64_t index_lower = -1; 749554f68d3SGreg Clayton int64_t index_higher = -1; 750554f68d3SGreg Clayton bool is_array_range = false; 751554f68d3SGreg Clayton bool was_plain_var = false; 752554f68d3SGreg Clayton bool was_var_format = false; 753554f68d3SGreg Clayton bool was_var_indexed = false; 754b9c1b51eSKate Stone ValueObject::ExpressionPathScanEndReason reason_to_stop = 755b9c1b51eSKate Stone ValueObject::eExpressionPathScanEndReasonEndOfString; 756b9c1b51eSKate Stone ValueObject::ExpressionPathEndResultType final_value_type = 757b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypePlain; 758554f68d3SGreg Clayton 759b9c1b51eSKate Stone if (is_script) { 760554f68d3SGreg Clayton return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); 761554f68d3SGreg Clayton } 762554f68d3SGreg Clayton 763554f68d3SGreg Clayton llvm::StringRef subpath(entry.string); 764554f68d3SGreg Clayton // simplest case ${var}, just print valobj's value 765b9c1b51eSKate Stone if (entry.string.empty()) { 766b9c1b51eSKate Stone if (entry.printf_format.empty() && entry.fmt == eFormatDefault && 767b9c1b51eSKate Stone entry.number == ValueObject::eValueObjectRepresentationStyleValue) 768554f68d3SGreg Clayton was_plain_var = true; 769554f68d3SGreg Clayton else 770554f68d3SGreg Clayton was_var_format = true; 771554f68d3SGreg Clayton target = valobj; 772b9c1b51eSKate Stone } else // this is ${var.something} or multiple .something nested 773554f68d3SGreg Clayton { 774554f68d3SGreg Clayton if (entry.string[0] == '[') 775554f68d3SGreg Clayton was_var_indexed = true; 776b9c1b51eSKate Stone ScanBracketedRange(subpath, close_bracket_index, 777b9c1b51eSKate Stone var_name_final_if_array_range, index_lower, 778554f68d3SGreg Clayton index_higher); 779554f68d3SGreg Clayton 78097206d57SZachary Turner Status error; 781554f68d3SGreg Clayton 782554f68d3SGreg Clayton const std::string &expr_path = entry.string; 783554f68d3SGreg Clayton 784554f68d3SGreg Clayton if (log) 785b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", 786b9c1b51eSKate Stone expr_path.c_str()); 787554f68d3SGreg Clayton 788d2daca77SZachary Turner target = 789d2daca77SZachary Turner valobj 790d2daca77SZachary Turner ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, 791d2daca77SZachary Turner &final_value_type, options, &what_next) 792b9c1b51eSKate Stone .get(); 793554f68d3SGreg Clayton 794b9c1b51eSKate Stone if (!target) { 795554f68d3SGreg Clayton if (log) 796d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d," 797655c4525SZachary Turner " final_value_type %d", 798d2daca77SZachary Turner reason_to_stop, final_value_type); 799554f68d3SGreg Clayton return false; 800b9c1b51eSKate Stone } else { 801554f68d3SGreg Clayton if (log) 802d2daca77SZachary Turner log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," 803655c4525SZachary Turner " final_value_type %d", 804d2daca77SZachary Turner reason_to_stop, final_value_type); 805b9c1b51eSKate Stone target = target 806b9c1b51eSKate Stone ->GetQualifiedRepresentationIfAvailable( 807b9c1b51eSKate Stone target->GetDynamicValueType(), true) 808b9c1b51eSKate Stone .get(); 809554f68d3SGreg Clayton } 810554f68d3SGreg Clayton } 811554f68d3SGreg Clayton 812b9c1b51eSKate Stone is_array_range = 813b9c1b51eSKate Stone (final_value_type == 814b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeBoundedRange || 815b9c1b51eSKate Stone final_value_type == 816b9c1b51eSKate Stone ValueObject::eExpressionPathEndResultTypeUnboundedRange); 817554f68d3SGreg Clayton 818b9c1b51eSKate Stone do_deref_pointer = 819b9c1b51eSKate Stone (what_next == ValueObject::eExpressionPathAftermathDereference); 820554f68d3SGreg Clayton 821b9c1b51eSKate Stone if (do_deref_pointer && !is_array_range) { 822554f68d3SGreg Clayton // I have not deref-ed yet, let's do it 823b9c1b51eSKate Stone // this happens when we are not going through 82405097246SAdrian Prantl // GetValueForVariableExpressionPath to get to the target ValueObject 82597206d57SZachary Turner Status error; 826554f68d3SGreg Clayton target = target->Dereference(error).get(); 827b9c1b51eSKate Stone if (error.Fail()) { 828554f68d3SGreg Clayton if (log) 829b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", 830b9c1b51eSKate Stone error.AsCString("unknown")); 831554f68d3SGreg Clayton return false; 832554f68d3SGreg Clayton } 833554f68d3SGreg Clayton do_deref_pointer = false; 834554f68d3SGreg Clayton } 835554f68d3SGreg Clayton 836b9c1b51eSKate Stone if (!target) { 837554f68d3SGreg Clayton if (log) 838b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] could not calculate target for " 839b9c1b51eSKate Stone "prompt expression"); 840554f68d3SGreg Clayton return false; 841554f68d3SGreg Clayton } 842554f68d3SGreg Clayton 84305097246SAdrian Prantl // we do not want to use the summary for a bitfield of type T:n if we were 84405097246SAdrian Prantl // originally dealing with just a T - that would get us into an endless 84505097246SAdrian Prantl // recursion 846b9c1b51eSKate Stone if (target->IsBitfield() && was_var_indexed) { 847554f68d3SGreg Clayton // TODO: check for a (T:n)-specific summary - we should still obey that 848554f68d3SGreg Clayton StreamString bitfield_name; 849b9c1b51eSKate Stone bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), 850b9c1b51eSKate Stone target->GetBitfieldBitSize()); 8512f3df613SZachary Turner auto type_sp = std::make_shared<TypeNameSpecifierImpl>( 8522f3df613SZachary Turner bitfield_name.GetString(), false); 853b9c1b51eSKate Stone if (val_obj_display == 854b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary && 855b9c1b51eSKate Stone !DataVisualization::GetSummaryForType(type_sp)) 856554f68d3SGreg Clayton val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 857554f68d3SGreg Clayton } 858554f68d3SGreg Clayton 859554f68d3SGreg Clayton // TODO use flags for these 860b9c1b51eSKate Stone const uint32_t type_info_flags = 861b9c1b51eSKate Stone target->GetCompilerType().GetTypeInfo(nullptr); 862554f68d3SGreg Clayton bool is_array = (type_info_flags & eTypeIsArray) != 0; 863554f68d3SGreg Clayton bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 86499558cc4SGreg Clayton bool is_aggregate = target->GetCompilerType().IsAggregateType(); 865554f68d3SGreg Clayton 866b9c1b51eSKate Stone if ((is_array || is_pointer) && (!is_array_range) && 867b9c1b51eSKate Stone val_obj_display == 868b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue) // this should be 869b9c1b51eSKate Stone // wrong, but there 870b9c1b51eSKate Stone // are some 871b9c1b51eSKate Stone // exceptions 872554f68d3SGreg Clayton { 873554f68d3SGreg Clayton StreamString str_temp; 874554f68d3SGreg Clayton if (log) 875b9c1b51eSKate Stone log->Printf( 876b9c1b51eSKate Stone "[Debugger::FormatPrompt] I am into array || pointer && !range"); 877554f68d3SGreg Clayton 878b9c1b51eSKate Stone if (target->HasSpecialPrintableRepresentation(val_obj_display, 879b9c1b51eSKate Stone custom_format)) { 880554f68d3SGreg Clayton // try to use the special cases 881b9c1b51eSKate Stone bool success = target->DumpPrintableRepresentation( 882b9c1b51eSKate Stone str_temp, val_obj_display, custom_format); 883554f68d3SGreg Clayton if (log) 884b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] special cases did%s match", 885b9c1b51eSKate Stone success ? "" : "n't"); 886554f68d3SGreg Clayton 887554f68d3SGreg Clayton // should not happen 888554f68d3SGreg Clayton if (success) 889c156427dSZachary Turner s << str_temp.GetString(); 890554f68d3SGreg Clayton return true; 891b9c1b51eSKate Stone } else { 892554f68d3SGreg Clayton if (was_plain_var) // if ${var} 893554f68d3SGreg Clayton { 894554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 895b9c1b51eSKate Stone } else if (is_pointer) // if pointer, value is the address stored 896554f68d3SGreg Clayton { 897b9c1b51eSKate Stone target->DumpPrintableRepresentation( 898b9c1b51eSKate Stone s, val_obj_display, custom_format, 89965d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable); 900554f68d3SGreg Clayton } 901554f68d3SGreg Clayton return true; 902554f68d3SGreg Clayton } 903554f68d3SGreg Clayton } 904554f68d3SGreg Clayton 905b9c1b51eSKate Stone // if directly trying to print ${var}, and this is an aggregate, display a 90605097246SAdrian Prantl // nice type @ location message 907b9c1b51eSKate Stone if (is_aggregate && was_plain_var) { 908554f68d3SGreg Clayton s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 909554f68d3SGreg Clayton return true; 910554f68d3SGreg Clayton } 911554f68d3SGreg Clayton 912b9c1b51eSKate Stone // if directly trying to print ${var%V}, and this is an aggregate, do not let 913b9c1b51eSKate Stone // the user do it 914b9c1b51eSKate Stone if (is_aggregate && 915b9c1b51eSKate Stone ((was_var_format && 916b9c1b51eSKate Stone val_obj_display == 917b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue))) { 918554f68d3SGreg Clayton s << "<invalid use of aggregate type>"; 919554f68d3SGreg Clayton return true; 920554f68d3SGreg Clayton } 921554f68d3SGreg Clayton 922b9c1b51eSKate Stone if (!is_array_range) { 923554f68d3SGreg Clayton if (log) 924554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 925b9c1b51eSKate Stone return target->DumpPrintableRepresentation(s, val_obj_display, 926b9c1b51eSKate Stone custom_format); 927b9c1b51eSKate Stone } else { 928554f68d3SGreg Clayton if (log) 929554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 930554f68d3SGreg Clayton if (!is_array && !is_pointer) 931554f68d3SGreg Clayton return false; 932554f68d3SGreg Clayton if (log) 933554f68d3SGreg Clayton log->Printf("[Debugger::FormatPrompt] handle as array"); 934e8376261SVince Harron StreamString special_directions_stream; 935554f68d3SGreg Clayton llvm::StringRef special_directions; 936b9c1b51eSKate Stone if (close_bracket_index != llvm::StringRef::npos && 937b9c1b51eSKate Stone subpath.size() > close_bracket_index) { 938554f68d3SGreg Clayton ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); 939b9c1b51eSKate Stone special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", 940554f68d3SGreg Clayton additional_data.GetCString()); 941554f68d3SGreg Clayton 942b9c1b51eSKate Stone if (entry.fmt != eFormatDefault) { 943b9c1b51eSKate Stone const char format_char = 944b9c1b51eSKate Stone FormatManager::GetFormatAsFormatChar(entry.fmt); 945554f68d3SGreg Clayton if (format_char != '\0') 946554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", format_char); 947b9c1b51eSKate Stone else { 948b9c1b51eSKate Stone const char *format_cstr = 949b9c1b51eSKate Stone FormatManager::GetFormatAsCString(entry.fmt); 950554f68d3SGreg Clayton special_directions_stream.Printf("%%%s", format_cstr); 951554f68d3SGreg Clayton } 952b9c1b51eSKate Stone } else if (entry.number != 0) { 953b9c1b51eSKate Stone const char style_char = ConvertValueObjectStyleToChar( 954b9c1b51eSKate Stone (ValueObject::ValueObjectRepresentationStyle)entry.number); 955554f68d3SGreg Clayton if (style_char) 956554f68d3SGreg Clayton special_directions_stream.Printf("%%%c", style_char); 957554f68d3SGreg Clayton } 958554f68d3SGreg Clayton special_directions_stream.PutChar('}'); 959b9c1b51eSKate Stone special_directions = 960b9c1b51eSKate Stone llvm::StringRef(special_directions_stream.GetString()); 961554f68d3SGreg Clayton } 962554f68d3SGreg Clayton 963554f68d3SGreg Clayton // let us display items index_lower thru index_higher of this array 964554f68d3SGreg Clayton s.PutChar('['); 965554f68d3SGreg Clayton 966554f68d3SGreg Clayton if (index_higher < 0) 967554f68d3SGreg Clayton index_higher = valobj->GetNumChildren() - 1; 968554f68d3SGreg Clayton 969b9c1b51eSKate Stone uint32_t max_num_children = 970b9c1b51eSKate Stone target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 971554f68d3SGreg Clayton 972554f68d3SGreg Clayton bool success = true; 973b9c1b51eSKate Stone for (int64_t index = index_lower; index <= index_higher; ++index) { 974b9c1b51eSKate Stone ValueObject *item = 975b9c1b51eSKate Stone ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) 976b9c1b51eSKate Stone .get(); 977554f68d3SGreg Clayton 978b9c1b51eSKate Stone if (!item) { 979554f68d3SGreg Clayton if (log) 980b9c1b51eSKate Stone log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " 981b9c1b51eSKate Stone "index %" PRId64, 982b9c1b51eSKate Stone index); 983b9c1b51eSKate Stone } else { 984554f68d3SGreg Clayton if (log) 985b9c1b51eSKate Stone log->Printf( 986b9c1b51eSKate Stone "[Debugger::FormatPrompt] special_directions for child item: %s", 987b9c1b51eSKate Stone special_directions.data() ? special_directions.data() : ""); 988554f68d3SGreg Clayton } 989554f68d3SGreg Clayton 990b9c1b51eSKate Stone if (special_directions.empty()) { 991b9c1b51eSKate Stone success &= item->DumpPrintableRepresentation(s, val_obj_display, 992b9c1b51eSKate Stone custom_format); 993b9c1b51eSKate Stone } else { 994b9c1b51eSKate Stone success &= FormatEntity::FormatStringRef( 995b9c1b51eSKate Stone special_directions, s, sc, exe_ctx, nullptr, item, false, false); 996554f68d3SGreg Clayton } 997554f68d3SGreg Clayton 998b9c1b51eSKate Stone if (--max_num_children == 0) { 999554f68d3SGreg Clayton s.PutCString(", ..."); 1000554f68d3SGreg Clayton break; 1001554f68d3SGreg Clayton } 1002554f68d3SGreg Clayton 1003554f68d3SGreg Clayton if (index < index_higher) 1004554f68d3SGreg Clayton s.PutChar(','); 1005554f68d3SGreg Clayton } 1006554f68d3SGreg Clayton s.PutChar(']'); 1007554f68d3SGreg Clayton return success; 1008554f68d3SGreg Clayton } 1009554f68d3SGreg Clayton } 1010554f68d3SGreg Clayton 1011b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, 1012b9c1b51eSKate Stone Format format) { 1013b9c1b51eSKate Stone if (frame) { 1014554f68d3SGreg Clayton RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 1015554f68d3SGreg Clayton 1016b9c1b51eSKate Stone if (reg_ctx) { 1017554f68d3SGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 1018b9c1b51eSKate Stone if (reg_info) { 1019554f68d3SGreg Clayton RegisterValue reg_value; 1020b9c1b51eSKate Stone if (reg_ctx->ReadRegister(reg_info, reg_value)) { 1021554f68d3SGreg Clayton reg_value.Dump(&s, reg_info, false, false, format); 1022554f68d3SGreg Clayton return true; 1023554f68d3SGreg Clayton } 1024554f68d3SGreg Clayton } 1025554f68d3SGreg Clayton } 1026554f68d3SGreg Clayton } 1027554f68d3SGreg Clayton return false; 1028554f68d3SGreg Clayton } 1029554f68d3SGreg Clayton 1030b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse( 1031b9c1b51eSKate Stone const FormatEntity::Entry &entry, 1032554f68d3SGreg Clayton const StructuredData::ObjectSP &thread_info_dictionary, 1033b9c1b51eSKate Stone const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { 1034554f68d3SGreg Clayton llvm::StringRef path(entry.string); 1035554f68d3SGreg Clayton 1036b9c1b51eSKate Stone StructuredData::ObjectSP value = 1037b9c1b51eSKate Stone thread_info_dictionary->GetObjectForDotSeparatedPath(path); 1038554f68d3SGreg Clayton 1039b9c1b51eSKate Stone if (value) { 10405bfee5f1SAbhishek Aggarwal if (value->GetType() == eStructuredDataTypeInteger) { 1041554f68d3SGreg Clayton const char *token_format = "0x%4.4" PRIx64; 1042554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1043554f68d3SGreg Clayton token_format = entry.printf_format.c_str(); 1044554f68d3SGreg Clayton s.Printf(token_format, value->GetAsInteger()->GetValue()); 1045554f68d3SGreg Clayton return true; 10465bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeFloat) { 1047554f68d3SGreg Clayton s.Printf("%f", value->GetAsFloat()->GetValue()); 1048554f68d3SGreg Clayton return true; 10495bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeString) { 10502833321fSZachary Turner s.Format("{0}", value->GetAsString()->GetValue()); 1051554f68d3SGreg Clayton return true; 10525bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeArray) { 1053b9c1b51eSKate Stone if (value->GetAsArray()->GetSize() > 0) { 1054554f68d3SGreg Clayton s.Printf("%zu", value->GetAsArray()->GetSize()); 1055554f68d3SGreg Clayton return true; 1056554f68d3SGreg Clayton } 10575bfee5f1SAbhishek Aggarwal } else if (value->GetType() == eStructuredDataTypeDictionary) { 1058b9c1b51eSKate Stone s.Printf("%zu", 1059b9c1b51eSKate Stone value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1060554f68d3SGreg Clayton return true; 1061554f68d3SGreg Clayton } 1062554f68d3SGreg Clayton } 1063554f68d3SGreg Clayton 1064554f68d3SGreg Clayton return false; 1065554f68d3SGreg Clayton } 1066554f68d3SGreg Clayton 1067b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) { 1068554f68d3SGreg Clayton return (::strncmp(var_name_begin, var, strlen(var)) == 0); 1069554f68d3SGreg Clayton } 1070554f68d3SGreg Clayton 1071b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, 1072554f68d3SGreg Clayton const SymbolContext *sc, 1073554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1074b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1075554f68d3SGreg Clayton bool function_changed, 1076b9c1b51eSKate Stone bool initial_function) { 1077b9c1b51eSKate Stone if (!format_str.empty()) { 1078554f68d3SGreg Clayton FormatEntity::Entry root; 107997206d57SZachary Turner Status error = FormatEntity::Parse(format_str, root); 1080b9c1b51eSKate Stone if (error.Success()) { 1081b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1082b9c1b51eSKate Stone function_changed, initial_function); 1083554f68d3SGreg Clayton } 1084554f68d3SGreg Clayton } 1085554f68d3SGreg Clayton return false; 1086554f68d3SGreg Clayton } 1087a74f37a5SEugene Zelenko 1088b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s, 1089554f68d3SGreg Clayton const SymbolContext *sc, 1090554f68d3SGreg Clayton const ExecutionContext *exe_ctx, 1091b9c1b51eSKate Stone const Address *addr, ValueObject *valobj, 1092b9c1b51eSKate Stone bool function_changed, bool initial_function) { 1093b9c1b51eSKate Stone if (format && format[0]) { 1094554f68d3SGreg Clayton FormatEntity::Entry root; 1095554f68d3SGreg Clayton llvm::StringRef format_str(format); 109697206d57SZachary Turner Status error = FormatEntity::Parse(format_str, root); 1097b9c1b51eSKate Stone if (error.Success()) { 1098b9c1b51eSKate Stone return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, 1099b9c1b51eSKate Stone function_changed, initial_function); 1100554f68d3SGreg Clayton } 1101554f68d3SGreg Clayton } 1102554f68d3SGreg Clayton return false; 1103554f68d3SGreg Clayton } 1104554f68d3SGreg Clayton 1105b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s, 1106554f68d3SGreg Clayton const SymbolContext *sc, 1107b9c1b51eSKate Stone const ExecutionContext *exe_ctx, const Address *addr, 1108b9c1b51eSKate Stone ValueObject *valobj, bool function_changed, 1109b9c1b51eSKate Stone bool initial_function) { 1110b9c1b51eSKate Stone switch (entry.type) { 1111554f68d3SGreg Clayton case Entry::Type::Invalid: 1112b9c1b51eSKate Stone case Entry::Type::ParentNumber: // Only used for 1113b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1114b9c1b51eSKate Stone case Entry::Type::ParentString: // Only used for 1115b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1116b9c1b51eSKate Stone case Entry::Type::InsertString: // Only used for 1117b9c1b51eSKate Stone // FormatEntity::Entry::Definition encoding 1118554f68d3SGreg Clayton return false; 1119554f68d3SGreg Clayton 1120554f68d3SGreg Clayton case Entry::Type::Root: 1121b9c1b51eSKate Stone for (const auto &child : entry.children) { 1122b9c1b51eSKate Stone if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, 1123b9c1b51eSKate Stone initial_function)) { 1124554f68d3SGreg Clayton return false; // If any item of root fails, then the formatting fails 1125554f68d3SGreg Clayton } 1126554f68d3SGreg Clayton } 1127554f68d3SGreg Clayton return true; // Only return true if all items succeeded 1128554f68d3SGreg Clayton 1129554f68d3SGreg Clayton case Entry::Type::String: 1130771ef6d4SMalcolm Parsons s.PutCString(entry.string); 1131554f68d3SGreg Clayton return true; 1132554f68d3SGreg Clayton 1133b9c1b51eSKate Stone case Entry::Type::Scope: { 1134554f68d3SGreg Clayton StreamString scope_stream; 1135554f68d3SGreg Clayton bool success = false; 1136b9c1b51eSKate Stone for (const auto &child : entry.children) { 1137b9c1b51eSKate Stone success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, 1138b9c1b51eSKate Stone function_changed, initial_function); 1139554f68d3SGreg Clayton if (!success) 1140554f68d3SGreg Clayton break; 1141554f68d3SGreg Clayton } 114205097246SAdrian Prantl // Only if all items in a scope succeed, then do we print the output into 114305097246SAdrian Prantl // the main stream 1144554f68d3SGreg Clayton if (success) 1145554f68d3SGreg Clayton s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1146554f68d3SGreg Clayton } 1147554f68d3SGreg Clayton return true; // Scopes always successfully print themselves 1148554f68d3SGreg Clayton 1149554f68d3SGreg Clayton case Entry::Type::Variable: 1150554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 1151554f68d3SGreg Clayton case Entry::Type::ScriptVariable: 1152554f68d3SGreg Clayton case Entry::Type::ScriptVariableSynthetic: 1153a74f37a5SEugene Zelenko return DumpValue(s, sc, exe_ctx, entry, valobj); 1154554f68d3SGreg Clayton 1155554f68d3SGreg Clayton case Entry::Type::AddressFile: 1156554f68d3SGreg Clayton case Entry::Type::AddressLoad: 1157554f68d3SGreg Clayton case Entry::Type::AddressLoadOrFile: 1158a74f37a5SEugene Zelenko return (addr != nullptr && addr->IsValid() && 1159b9c1b51eSKate Stone DumpAddress(s, sc, exe_ctx, *addr, 1160b9c1b51eSKate Stone entry.type == Entry::Type::AddressLoadOrFile)); 1161554f68d3SGreg Clayton 1162554f68d3SGreg Clayton case Entry::Type::ProcessID: 1163b9c1b51eSKate Stone if (exe_ctx) { 1164554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1165b9c1b51eSKate Stone if (process) { 1166554f68d3SGreg Clayton const char *format = "%" PRIu64; 1167554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1168554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1169554f68d3SGreg Clayton s.Printf(format, process->GetID()); 1170554f68d3SGreg Clayton return true; 1171554f68d3SGreg Clayton } 1172554f68d3SGreg Clayton } 1173554f68d3SGreg Clayton return false; 1174554f68d3SGreg Clayton 1175554f68d3SGreg Clayton case Entry::Type::ProcessFile: 1176b9c1b51eSKate Stone if (exe_ctx) { 1177554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1178b9c1b51eSKate Stone if (process) { 1179554f68d3SGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1180b9c1b51eSKate Stone if (exe_module) { 1181554f68d3SGreg Clayton if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1182554f68d3SGreg Clayton return true; 1183554f68d3SGreg Clayton } 1184554f68d3SGreg Clayton } 1185554f68d3SGreg Clayton } 1186554f68d3SGreg Clayton return false; 1187554f68d3SGreg Clayton 1188554f68d3SGreg Clayton case Entry::Type::ScriptProcess: 1189b9c1b51eSKate Stone if (exe_ctx) { 1190554f68d3SGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1191554f68d3SGreg Clayton if (process) 1192b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, process, 1193b9c1b51eSKate Stone entry.string.c_str()); 1194554f68d3SGreg Clayton } 1195554f68d3SGreg Clayton return false; 1196554f68d3SGreg Clayton 1197554f68d3SGreg Clayton case Entry::Type::ThreadID: 1198b9c1b51eSKate Stone if (exe_ctx) { 1199554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1200b9c1b51eSKate Stone if (thread) { 1201554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1202b9c1b51eSKate Stone if (!entry.printf_format.empty()) { 1203554f68d3SGreg Clayton // Watch for the special "tid" format... 1204b9c1b51eSKate Stone if (entry.printf_format == "tid") { 1205b9c1b51eSKate Stone // TODO(zturner): Rather than hardcoding this to be platform 120605097246SAdrian Prantl // specific, it should be controlled by a setting and the default 120705097246SAdrian Prantl // value of the setting can be different depending on the platform. 1208554f68d3SGreg Clayton Target &target = thread->GetProcess()->GetTarget(); 1209554f68d3SGreg Clayton ArchSpec arch(target.GetArchitecture()); 1210b9c1b51eSKate Stone llvm::Triple::OSType ostype = arch.IsValid() 1211b9c1b51eSKate Stone ? arch.GetTriple().getOS() 1212b9c1b51eSKate Stone : llvm::Triple::UnknownOS; 1213b9c1b51eSKate Stone if ((ostype == llvm::Triple::FreeBSD) || 1214750228a6SKamil Rytarowski (ostype == llvm::Triple::Linux) || 1215750228a6SKamil Rytarowski (ostype == llvm::Triple::NetBSD)) { 1216554f68d3SGreg Clayton format = "%" PRIu64; 1217554f68d3SGreg Clayton } 1218b9c1b51eSKate Stone } else { 1219554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1220554f68d3SGreg Clayton } 1221554f68d3SGreg Clayton } 1222554f68d3SGreg Clayton s.Printf(format, thread->GetID()); 1223554f68d3SGreg Clayton return true; 1224554f68d3SGreg Clayton } 1225554f68d3SGreg Clayton } 1226554f68d3SGreg Clayton return false; 1227554f68d3SGreg Clayton 1228554f68d3SGreg Clayton case Entry::Type::ThreadProtocolID: 1229b9c1b51eSKate Stone if (exe_ctx) { 1230554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1231b9c1b51eSKate Stone if (thread) { 1232554f68d3SGreg Clayton const char *format = "0x%4.4" PRIx64; 1233554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1234554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1235554f68d3SGreg Clayton s.Printf(format, thread->GetProtocolID()); 1236554f68d3SGreg Clayton return true; 1237554f68d3SGreg Clayton } 1238554f68d3SGreg Clayton } 1239554f68d3SGreg Clayton return false; 1240554f68d3SGreg Clayton 1241554f68d3SGreg Clayton case Entry::Type::ThreadIndexID: 1242b9c1b51eSKate Stone if (exe_ctx) { 1243554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1244b9c1b51eSKate Stone if (thread) { 1245554f68d3SGreg Clayton const char *format = "%" PRIu32; 1246554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1247554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1248554f68d3SGreg Clayton s.Printf(format, thread->GetIndexID()); 1249554f68d3SGreg Clayton return true; 1250554f68d3SGreg Clayton } 1251554f68d3SGreg Clayton } 1252554f68d3SGreg Clayton return false; 1253554f68d3SGreg Clayton 1254554f68d3SGreg Clayton case Entry::Type::ThreadName: 1255b9c1b51eSKate Stone if (exe_ctx) { 1256554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1257b9c1b51eSKate Stone if (thread) { 1258554f68d3SGreg Clayton const char *cstr = thread->GetName(); 1259b9c1b51eSKate Stone if (cstr && cstr[0]) { 1260554f68d3SGreg Clayton s.PutCString(cstr); 1261554f68d3SGreg Clayton return true; 1262554f68d3SGreg Clayton } 1263554f68d3SGreg Clayton } 1264554f68d3SGreg Clayton } 1265554f68d3SGreg Clayton return false; 1266554f68d3SGreg Clayton 1267554f68d3SGreg Clayton case Entry::Type::ThreadQueue: 1268b9c1b51eSKate Stone if (exe_ctx) { 1269554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1270b9c1b51eSKate Stone if (thread) { 1271554f68d3SGreg Clayton const char *cstr = thread->GetQueueName(); 1272b9c1b51eSKate Stone if (cstr && cstr[0]) { 1273554f68d3SGreg Clayton s.PutCString(cstr); 1274554f68d3SGreg Clayton return true; 1275554f68d3SGreg Clayton } 1276554f68d3SGreg Clayton } 1277554f68d3SGreg Clayton } 1278554f68d3SGreg Clayton return false; 1279554f68d3SGreg Clayton 1280554f68d3SGreg Clayton case Entry::Type::ThreadStopReason: 1281b9c1b51eSKate Stone if (exe_ctx) { 1282554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1283b9c1b51eSKate Stone if (thread) { 1284554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1285b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1286554f68d3SGreg Clayton const char *cstr = stop_info_sp->GetDescription(); 1287b9c1b51eSKate Stone if (cstr && cstr[0]) { 1288554f68d3SGreg Clayton s.PutCString(cstr); 1289554f68d3SGreg Clayton return true; 1290554f68d3SGreg Clayton } 1291554f68d3SGreg Clayton } 1292554f68d3SGreg Clayton } 1293554f68d3SGreg Clayton } 1294554f68d3SGreg Clayton return false; 1295554f68d3SGreg Clayton 1296554f68d3SGreg Clayton case Entry::Type::ThreadReturnValue: 1297b9c1b51eSKate Stone if (exe_ctx) { 1298554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1299b9c1b51eSKate Stone if (thread) { 1300554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1301b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1302b9c1b51eSKate Stone ValueObjectSP return_valobj_sp = 1303b9c1b51eSKate Stone StopInfo::GetReturnValueObject(stop_info_sp); 1304b9c1b51eSKate Stone if (return_valobj_sp) { 1305554f68d3SGreg Clayton return_valobj_sp->Dump(s); 1306554f68d3SGreg Clayton return true; 1307554f68d3SGreg Clayton } 1308554f68d3SGreg Clayton } 1309554f68d3SGreg Clayton } 1310554f68d3SGreg Clayton } 1311554f68d3SGreg Clayton return false; 1312554f68d3SGreg Clayton 1313554f68d3SGreg Clayton case Entry::Type::ThreadCompletedExpression: 1314b9c1b51eSKate Stone if (exe_ctx) { 1315554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1316b9c1b51eSKate Stone if (thread) { 1317554f68d3SGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo(); 1318b9c1b51eSKate Stone if (stop_info_sp && stop_info_sp->IsValid()) { 1319b9c1b51eSKate Stone ExpressionVariableSP expression_var_sp = 1320b9c1b51eSKate Stone StopInfo::GetExpressionVariable(stop_info_sp); 1321b9c1b51eSKate Stone if (expression_var_sp && expression_var_sp->GetValueObject()) { 1322554f68d3SGreg Clayton expression_var_sp->GetValueObject()->Dump(s); 1323554f68d3SGreg Clayton return true; 1324554f68d3SGreg Clayton } 1325554f68d3SGreg Clayton } 1326554f68d3SGreg Clayton } 1327554f68d3SGreg Clayton } 1328554f68d3SGreg Clayton return false; 1329554f68d3SGreg Clayton 1330554f68d3SGreg Clayton case Entry::Type::ScriptThread: 1331b9c1b51eSKate Stone if (exe_ctx) { 1332554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1333554f68d3SGreg Clayton if (thread) 1334b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, thread, 1335b9c1b51eSKate Stone entry.string.c_str()); 1336554f68d3SGreg Clayton } 1337554f68d3SGreg Clayton return false; 1338554f68d3SGreg Clayton 1339554f68d3SGreg Clayton case Entry::Type::ThreadInfo: 1340b9c1b51eSKate Stone if (exe_ctx) { 1341554f68d3SGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1342b9c1b51eSKate Stone if (thread) { 1343554f68d3SGreg Clayton StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1344b9c1b51eSKate Stone if (object_sp && 13455bfee5f1SAbhishek Aggarwal object_sp->GetType() == eStructuredDataTypeDictionary) { 1346554f68d3SGreg Clayton if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) 1347554f68d3SGreg Clayton return true; 1348554f68d3SGreg Clayton } 1349554f68d3SGreg Clayton } 1350554f68d3SGreg Clayton } 1351554f68d3SGreg Clayton return false; 1352554f68d3SGreg Clayton 1353554f68d3SGreg Clayton case Entry::Type::TargetArch: 1354b9c1b51eSKate Stone if (exe_ctx) { 1355554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1356b9c1b51eSKate Stone if (target) { 1357554f68d3SGreg Clayton const ArchSpec &arch = target->GetArchitecture(); 1358b9c1b51eSKate Stone if (arch.IsValid()) { 1359554f68d3SGreg Clayton s.PutCString(arch.GetArchitectureName()); 1360554f68d3SGreg Clayton return true; 1361554f68d3SGreg Clayton } 1362554f68d3SGreg Clayton } 1363554f68d3SGreg Clayton } 1364554f68d3SGreg Clayton return false; 1365554f68d3SGreg Clayton 1366554f68d3SGreg Clayton case Entry::Type::ScriptTarget: 1367b9c1b51eSKate Stone if (exe_ctx) { 1368554f68d3SGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1369554f68d3SGreg Clayton if (target) 1370b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, target, 1371b9c1b51eSKate Stone entry.string.c_str()); 1372554f68d3SGreg Clayton } 1373554f68d3SGreg Clayton return false; 1374554f68d3SGreg Clayton 1375554f68d3SGreg Clayton case Entry::Type::ModuleFile: 1376b9c1b51eSKate Stone if (sc) { 1377554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1378b9c1b51eSKate Stone if (module) { 1379554f68d3SGreg Clayton if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1380554f68d3SGreg Clayton return true; 1381554f68d3SGreg Clayton } 1382554f68d3SGreg Clayton } 1383554f68d3SGreg Clayton return false; 1384554f68d3SGreg Clayton 1385554f68d3SGreg Clayton case Entry::Type::File: 1386b9c1b51eSKate Stone if (sc) { 1387554f68d3SGreg Clayton CompileUnit *cu = sc->comp_unit; 1388b9c1b51eSKate Stone if (cu) { 1389554f68d3SGreg Clayton // CompileUnit is a FileSpec 1390554f68d3SGreg Clayton if (DumpFile(s, *cu, (FileKind)entry.number)) 1391554f68d3SGreg Clayton return true; 1392554f68d3SGreg Clayton } 1393554f68d3SGreg Clayton } 1394554f68d3SGreg Clayton return false; 1395554f68d3SGreg Clayton 1396dc975670SDawn Perchik case Entry::Type::Lang: 1397b9c1b51eSKate Stone if (sc) { 1398dc975670SDawn Perchik CompileUnit *cu = sc->comp_unit; 1399b9c1b51eSKate Stone if (cu) { 1400b9c1b51eSKate Stone const char *lang_name = 1401b9c1b51eSKate Stone Language::GetNameForLanguageType(cu->GetLanguage()); 1402b9c1b51eSKate Stone if (lang_name) { 1403dc975670SDawn Perchik s.PutCString(lang_name); 1404dc975670SDawn Perchik return true; 1405dc975670SDawn Perchik } 1406dc975670SDawn Perchik } 1407dc975670SDawn Perchik } 1408dc975670SDawn Perchik return false; 1409dc975670SDawn Perchik 1410554f68d3SGreg Clayton case Entry::Type::FrameIndex: 1411b9c1b51eSKate Stone if (exe_ctx) { 1412554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1413b9c1b51eSKate Stone if (frame) { 1414554f68d3SGreg Clayton const char *format = "%" PRIu32; 1415554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1416554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1417554f68d3SGreg Clayton s.Printf(format, frame->GetFrameIndex()); 1418554f68d3SGreg Clayton return true; 1419554f68d3SGreg Clayton } 1420554f68d3SGreg Clayton } 1421554f68d3SGreg Clayton return false; 1422554f68d3SGreg Clayton 1423554f68d3SGreg Clayton case Entry::Type::FrameRegisterPC: 1424b9c1b51eSKate Stone if (exe_ctx) { 1425554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1426b9c1b51eSKate Stone if (frame) { 1427554f68d3SGreg Clayton const Address &pc_addr = frame->GetFrameCodeAddress(); 1428b9c1b51eSKate Stone if (pc_addr.IsValid()) { 1429554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) 1430554f68d3SGreg Clayton return true; 1431554f68d3SGreg Clayton } 1432554f68d3SGreg Clayton } 1433554f68d3SGreg Clayton } 1434554f68d3SGreg Clayton return false; 1435554f68d3SGreg Clayton 1436554f68d3SGreg Clayton case Entry::Type::FrameRegisterSP: 1437b9c1b51eSKate Stone if (exe_ctx) { 1438554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1439b9c1b51eSKate Stone if (frame) { 1440b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 1441b9c1b51eSKate Stone (lldb::Format)entry.number)) 1442554f68d3SGreg Clayton return true; 1443554f68d3SGreg Clayton } 1444554f68d3SGreg Clayton } 1445554f68d3SGreg Clayton return false; 1446554f68d3SGreg Clayton 1447554f68d3SGreg Clayton case Entry::Type::FrameRegisterFP: 1448b9c1b51eSKate Stone if (exe_ctx) { 1449554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1450b9c1b51eSKate Stone if (frame) { 1451b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, 1452b9c1b51eSKate Stone (lldb::Format)entry.number)) 1453554f68d3SGreg Clayton return true; 1454554f68d3SGreg Clayton } 1455554f68d3SGreg Clayton } 1456554f68d3SGreg Clayton return false; 1457554f68d3SGreg Clayton 1458554f68d3SGreg Clayton case Entry::Type::FrameRegisterFlags: 1459b9c1b51eSKate Stone if (exe_ctx) { 1460554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1461b9c1b51eSKate Stone if (frame) { 1462b9c1b51eSKate Stone if (DumpRegister(s, frame, eRegisterKindGeneric, 1463b9c1b51eSKate Stone LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1464554f68d3SGreg Clayton return true; 1465554f68d3SGreg Clayton } 1466554f68d3SGreg Clayton } 1467554f68d3SGreg Clayton return false; 1468554f68d3SGreg Clayton 14696a9767c7SJim Ingham case Entry::Type::FrameNoDebug: 14706a9767c7SJim Ingham if (exe_ctx) { 14716a9767c7SJim Ingham StackFrame *frame = exe_ctx->GetFramePtr(); 14726a9767c7SJim Ingham if (frame) { 14736a9767c7SJim Ingham return !frame->HasDebugInformation(); 14746a9767c7SJim Ingham } 14756a9767c7SJim Ingham } 14766a9767c7SJim Ingham return true; 14776a9767c7SJim Ingham 1478554f68d3SGreg Clayton case Entry::Type::FrameRegisterByName: 1479b9c1b51eSKate Stone if (exe_ctx) { 1480554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1481b9c1b51eSKate Stone if (frame) { 1482b9c1b51eSKate Stone if (DumpRegister(s, frame, entry.string.c_str(), 1483b9c1b51eSKate Stone (lldb::Format)entry.number)) 1484554f68d3SGreg Clayton return true; 1485554f68d3SGreg Clayton } 1486554f68d3SGreg Clayton } 1487554f68d3SGreg Clayton return false; 1488554f68d3SGreg Clayton 1489554f68d3SGreg Clayton case Entry::Type::ScriptFrame: 1490b9c1b51eSKate Stone if (exe_ctx) { 1491554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1492554f68d3SGreg Clayton if (frame) 1493b9c1b51eSKate Stone return RunScriptFormatKeyword(s, sc, exe_ctx, frame, 1494b9c1b51eSKate Stone entry.string.c_str()); 1495554f68d3SGreg Clayton } 1496554f68d3SGreg Clayton return false; 1497554f68d3SGreg Clayton 1498554f68d3SGreg Clayton case Entry::Type::FunctionID: 1499b9c1b51eSKate Stone if (sc) { 1500b9c1b51eSKate Stone if (sc->function) { 1501554f68d3SGreg Clayton s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1502554f68d3SGreg Clayton return true; 1503b9c1b51eSKate Stone } else if (sc->symbol) { 1504554f68d3SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 1505554f68d3SGreg Clayton return true; 1506554f68d3SGreg Clayton } 1507554f68d3SGreg Clayton } 1508554f68d3SGreg Clayton return false; 1509554f68d3SGreg Clayton 1510554f68d3SGreg Clayton case Entry::Type::FunctionDidChange: 1511554f68d3SGreg Clayton return function_changed; 1512554f68d3SGreg Clayton 1513554f68d3SGreg Clayton case Entry::Type::FunctionInitialFunction: 1514554f68d3SGreg Clayton return initial_function; 1515554f68d3SGreg Clayton 1516b9c1b51eSKate Stone case Entry::Type::FunctionName: { 1517d4129b47SEnrico Granata Language *language_plugin = nullptr; 1518d4129b47SEnrico Granata bool language_plugin_handled = false; 1519d4129b47SEnrico Granata StreamString ss; 1520d4129b47SEnrico Granata if (sc->function) 1521d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1522d4129b47SEnrico Granata else if (sc->symbol) 1523d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1524b9c1b51eSKate Stone if (language_plugin) { 1525b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1526b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); 1527d4129b47SEnrico Granata } 1528b9c1b51eSKate Stone if (language_plugin_handled) { 1529c156427dSZachary Turner s << ss.GetString(); 1530d4129b47SEnrico Granata return true; 1531b9c1b51eSKate Stone } else { 1532a74f37a5SEugene Zelenko const char *name = nullptr; 1533554f68d3SGreg Clayton if (sc->function) 1534a74f37a5SEugene Zelenko name = sc->function->GetName().AsCString(nullptr); 1535554f68d3SGreg Clayton else if (sc->symbol) 1536a74f37a5SEugene Zelenko name = sc->symbol->GetName().AsCString(nullptr); 1537b9c1b51eSKate Stone if (name) { 1538554f68d3SGreg Clayton s.PutCString(name); 1539554f68d3SGreg Clayton 1540b9c1b51eSKate Stone if (sc->block) { 1541554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1542b9c1b51eSKate Stone if (inline_block) { 1543b9c1b51eSKate Stone const InlineFunctionInfo *inline_info = 1544b9c1b51eSKate Stone sc->block->GetInlinedFunctionInfo(); 1545b9c1b51eSKate Stone if (inline_info) { 1546554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1547ddaf6a72SGreg Clayton inline_info->GetName(sc->function->GetLanguage()).Dump(&s); 1548554f68d3SGreg Clayton } 1549554f68d3SGreg Clayton } 1550554f68d3SGreg Clayton } 1551554f68d3SGreg Clayton return true; 1552554f68d3SGreg Clayton } 1553554f68d3SGreg Clayton } 1554d4129b47SEnrico Granata } 1555554f68d3SGreg Clayton return false; 1556554f68d3SGreg Clayton 1557b9c1b51eSKate Stone case Entry::Type::FunctionNameNoArgs: { 1558d4129b47SEnrico Granata Language *language_plugin = nullptr; 1559d4129b47SEnrico Granata bool language_plugin_handled = false; 1560d4129b47SEnrico Granata StreamString ss; 1561d4129b47SEnrico Granata if (sc->function) 1562d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1563d4129b47SEnrico Granata else if (sc->symbol) 1564d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1565b9c1b51eSKate Stone if (language_plugin) { 1566b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1567b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, 1568d4129b47SEnrico Granata ss); 1569d4129b47SEnrico Granata } 1570b9c1b51eSKate Stone if (language_plugin_handled) { 1571c156427dSZachary Turner s << ss.GetString(); 1572d4129b47SEnrico Granata return true; 1573b9c1b51eSKate Stone } else { 1574554f68d3SGreg Clayton ConstString name; 1575554f68d3SGreg Clayton if (sc->function) 1576ddaf6a72SGreg Clayton name = sc->function->GetNameNoArguments(); 1577554f68d3SGreg Clayton else if (sc->symbol) 1578ddaf6a72SGreg Clayton name = sc->symbol->GetNameNoArguments(); 1579b9c1b51eSKate Stone if (name) { 1580554f68d3SGreg Clayton s.PutCString(name.GetCString()); 1581554f68d3SGreg Clayton return true; 1582554f68d3SGreg Clayton } 1583554f68d3SGreg Clayton } 1584d4129b47SEnrico Granata } 1585554f68d3SGreg Clayton return false; 1586554f68d3SGreg Clayton 1587b9c1b51eSKate Stone case Entry::Type::FunctionNameWithArgs: { 1588d4129b47SEnrico Granata Language *language_plugin = nullptr; 1589d4129b47SEnrico Granata bool language_plugin_handled = false; 1590d4129b47SEnrico Granata StreamString ss; 1591d4129b47SEnrico Granata if (sc->function) 1592d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->function->GetLanguage()); 1593d4129b47SEnrico Granata else if (sc->symbol) 1594d4129b47SEnrico Granata language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); 1595b9c1b51eSKate Stone if (language_plugin) { 1596b9c1b51eSKate Stone language_plugin_handled = language_plugin->GetFunctionDisplayName( 1597b9c1b51eSKate Stone sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); 1598d4129b47SEnrico Granata } 1599b9c1b51eSKate Stone if (language_plugin_handled) { 1600c156427dSZachary Turner s << ss.GetString(); 1601d4129b47SEnrico Granata return true; 1602b9c1b51eSKate Stone } else { 1603554f68d3SGreg Clayton // Print the function name with arguments in it 1604b9c1b51eSKate Stone if (sc->function) { 1605b9c1b51eSKate Stone ExecutionContextScope *exe_scope = 1606b9c1b51eSKate Stone exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 1607a74f37a5SEugene Zelenko const char *cstr = sc->function->GetName().AsCString(nullptr); 1608b9c1b51eSKate Stone if (cstr) { 1609a74f37a5SEugene Zelenko const InlineFunctionInfo *inline_info = nullptr; 1610554f68d3SGreg Clayton VariableListSP variable_list_sp; 1611554f68d3SGreg Clayton bool get_function_vars = true; 1612b9c1b51eSKate Stone if (sc->block) { 1613554f68d3SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock(); 1614554f68d3SGreg Clayton 1615b9c1b51eSKate Stone if (inline_block) { 1616554f68d3SGreg Clayton get_function_vars = false; 1617554f68d3SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 1618554f68d3SGreg Clayton if (inline_info) 1619554f68d3SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList(true); 1620554f68d3SGreg Clayton } 1621554f68d3SGreg Clayton } 1622554f68d3SGreg Clayton 1623b9c1b51eSKate Stone if (get_function_vars) { 1624b9c1b51eSKate Stone variable_list_sp = 1625b9c1b51eSKate Stone sc->function->GetBlock(true).GetBlockVariableList(true); 1626554f68d3SGreg Clayton } 1627554f68d3SGreg Clayton 1628b9c1b51eSKate Stone if (inline_info) { 1629554f68d3SGreg Clayton s.PutCString(cstr); 1630554f68d3SGreg Clayton s.PutCString(" [inlined] "); 1631b9c1b51eSKate Stone cstr = 1632b9c1b51eSKate Stone inline_info->GetName(sc->function->GetLanguage()).GetCString(); 1633554f68d3SGreg Clayton } 1634554f68d3SGreg Clayton 1635554f68d3SGreg Clayton VariableList args; 1636554f68d3SGreg Clayton if (variable_list_sp) 1637b9c1b51eSKate Stone variable_list_sp->AppendVariablesWithScope( 1638b9c1b51eSKate Stone eValueTypeVariableArgument, args); 1639b9c1b51eSKate Stone if (args.GetSize() > 0) { 1640554f68d3SGreg Clayton const char *open_paren = strchr(cstr, '('); 1641554f68d3SGreg Clayton const char *close_paren = nullptr; 1642554f68d3SGreg Clayton const char *generic = strchr(cstr, '<'); 1643554f68d3SGreg Clayton // if before the arguments list begins there is a template sign 1644554f68d3SGreg Clayton // then scan to the end of the generic args before you try to find 1645554f68d3SGreg Clayton // the arguments list 1646b9c1b51eSKate Stone if (generic && open_paren && generic < open_paren) { 1647554f68d3SGreg Clayton int generic_depth = 1; 1648554f68d3SGreg Clayton ++generic; 1649b9c1b51eSKate Stone for (; *generic && generic_depth > 0; generic++) { 1650554f68d3SGreg Clayton if (*generic == '<') 1651554f68d3SGreg Clayton generic_depth++; 1652554f68d3SGreg Clayton if (*generic == '>') 1653554f68d3SGreg Clayton generic_depth--; 1654554f68d3SGreg Clayton } 1655554f68d3SGreg Clayton if (*generic) 1656554f68d3SGreg Clayton open_paren = strchr(generic, '('); 1657554f68d3SGreg Clayton else 1658554f68d3SGreg Clayton open_paren = nullptr; 1659554f68d3SGreg Clayton } 1660b9c1b51eSKate Stone if (open_paren) { 1661b9c1b51eSKate Stone if (IsToken(open_paren, "(anonymous namespace)")) { 1662b9c1b51eSKate Stone open_paren = 1663b9c1b51eSKate Stone strchr(open_paren + strlen("(anonymous namespace)"), '('); 1664554f68d3SGreg Clayton if (open_paren) 1665554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1666b9c1b51eSKate Stone } else 1667554f68d3SGreg Clayton close_paren = strchr(open_paren, ')'); 1668554f68d3SGreg Clayton } 1669554f68d3SGreg Clayton 1670554f68d3SGreg Clayton if (open_paren) 1671554f68d3SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 1672b9c1b51eSKate Stone else { 1673554f68d3SGreg Clayton s.PutCString(cstr); 1674554f68d3SGreg Clayton s.PutChar('('); 1675554f68d3SGreg Clayton } 1676554f68d3SGreg Clayton const size_t num_args = args.GetSize(); 1677b9c1b51eSKate Stone for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { 1678554f68d3SGreg Clayton std::string buffer; 1679554f68d3SGreg Clayton 1680554f68d3SGreg Clayton VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); 1681b9c1b51eSKate Stone ValueObjectSP var_value_sp( 1682b9c1b51eSKate Stone ValueObjectVariable::Create(exe_scope, var_sp)); 1683ad91c7ceSEnrico Granata StreamString ss; 1684c156427dSZachary Turner llvm::StringRef var_representation; 1685554f68d3SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 1686b9c1b51eSKate Stone if (var_value_sp->GetCompilerType().IsValid()) { 1687ad91c7ceSEnrico Granata if (var_value_sp && exe_scope->CalculateTarget()) 1688b9c1b51eSKate Stone var_value_sp = 1689b9c1b51eSKate Stone var_value_sp->GetQualifiedRepresentationIfAvailable( 1690b9c1b51eSKate Stone exe_scope->CalculateTarget() 1691b9c1b51eSKate Stone ->TargetProperties::GetPreferDynamicValue(), 1692b9c1b51eSKate Stone exe_scope->CalculateTarget() 1693b9c1b51eSKate Stone ->TargetProperties::GetEnableSyntheticValue()); 169499558cc4SGreg Clayton if (var_value_sp->GetCompilerType().IsAggregateType() && 1695b9c1b51eSKate Stone DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { 1696b9c1b51eSKate Stone static StringSummaryFormat format( 1697b9c1b51eSKate Stone TypeSummaryImpl::Flags() 1698554f68d3SGreg Clayton .SetHideItemNames(false) 1699554f68d3SGreg Clayton .SetShowMembersOneLiner(true), 1700554f68d3SGreg Clayton ""); 1701b9c1b51eSKate Stone format.FormatObject(var_value_sp.get(), buffer, 1702b9c1b51eSKate Stone TypeSummaryOptions()); 1703c156427dSZachary Turner var_representation = buffer; 1704b9c1b51eSKate Stone } else 1705b9c1b51eSKate Stone var_value_sp->DumpPrintableRepresentation( 1706b9c1b51eSKate Stone ss, ValueObject::ValueObjectRepresentationStyle:: 1707b9c1b51eSKate Stone eValueObjectRepresentationStyleSummary, 1708ad91c7ceSEnrico Granata eFormatDefault, 170965d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eAllow, 1710ad91c7ceSEnrico Granata false); 1711ad91c7ceSEnrico Granata } 1712ad91c7ceSEnrico Granata 1713c156427dSZachary Turner if (!ss.GetString().empty()) 1714c156427dSZachary Turner var_representation = ss.GetString(); 1715554f68d3SGreg Clayton if (arg_idx > 0) 1716554f68d3SGreg Clayton s.PutCString(", "); 1717b9c1b51eSKate Stone if (var_value_sp->GetError().Success()) { 1718c156427dSZachary Turner if (!var_representation.empty()) 1719c156427dSZachary Turner s.Printf("%s=%s", var_name, var_representation.str().c_str()); 1720554f68d3SGreg Clayton else 1721b9c1b51eSKate Stone s.Printf("%s=%s at %s", var_name, 1722b9c1b51eSKate Stone var_value_sp->GetTypeName().GetCString(), 1723b9c1b51eSKate Stone var_value_sp->GetLocationAsCString()); 1724b9c1b51eSKate Stone } else 1725554f68d3SGreg Clayton s.Printf("%s=<unavailable>", var_name); 1726554f68d3SGreg Clayton } 1727554f68d3SGreg Clayton 1728554f68d3SGreg Clayton if (close_paren) 1729554f68d3SGreg Clayton s.PutCString(close_paren); 1730554f68d3SGreg Clayton else 1731554f68d3SGreg Clayton s.PutChar(')'); 1732554f68d3SGreg Clayton 1733b9c1b51eSKate Stone } else { 1734554f68d3SGreg Clayton s.PutCString(cstr); 1735554f68d3SGreg Clayton } 1736554f68d3SGreg Clayton return true; 1737554f68d3SGreg Clayton } 1738b9c1b51eSKate Stone } else if (sc->symbol) { 1739a74f37a5SEugene Zelenko const char *cstr = sc->symbol->GetName().AsCString(nullptr); 1740b9c1b51eSKate Stone if (cstr) { 1741554f68d3SGreg Clayton s.PutCString(cstr); 1742554f68d3SGreg Clayton return true; 1743554f68d3SGreg Clayton } 1744554f68d3SGreg Clayton } 1745554f68d3SGreg Clayton } 1746d4129b47SEnrico Granata } 1747554f68d3SGreg Clayton return false; 1748554f68d3SGreg Clayton 1749554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffset: 1750b9c1b51eSKate Stone if (addr) { 1751b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, 1752b9c1b51eSKate Stone false)) 1753554f68d3SGreg Clayton return true; 1754554f68d3SGreg Clayton } 1755554f68d3SGreg Clayton return false; 1756554f68d3SGreg Clayton 1757554f68d3SGreg Clayton case Entry::Type::FunctionAddrOffsetConcrete: 1758b9c1b51eSKate Stone if (addr) { 1759b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, 1760b9c1b51eSKate Stone true)) 1761554f68d3SGreg Clayton return true; 1762554f68d3SGreg Clayton } 1763554f68d3SGreg Clayton return false; 1764554f68d3SGreg Clayton 1765554f68d3SGreg Clayton case Entry::Type::FunctionLineOffset: 1766b9c1b51eSKate Stone return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1767b9c1b51eSKate Stone sc->line_entry.range.GetBaseAddress(), 1768b9c1b51eSKate Stone false, false, false)); 1769554f68d3SGreg Clayton 1770554f68d3SGreg Clayton case Entry::Type::FunctionPCOffset: 1771b9c1b51eSKate Stone if (exe_ctx) { 1772554f68d3SGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 1773b9c1b51eSKate Stone if (frame) { 1774b9c1b51eSKate Stone if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, 1775b9c1b51eSKate Stone frame->GetFrameCodeAddress(), false, 1776b9c1b51eSKate Stone false, false)) 1777554f68d3SGreg Clayton return true; 1778554f68d3SGreg Clayton } 1779554f68d3SGreg Clayton } 1780554f68d3SGreg Clayton return false; 1781554f68d3SGreg Clayton 1782c980fa92SJason Molenda case Entry::Type::FunctionChanged: 1783a74f37a5SEugene Zelenko return function_changed; 1784c980fa92SJason Molenda 1785b9c1b51eSKate Stone case Entry::Type::FunctionIsOptimized: { 17866ab659a9SJason Molenda bool is_optimized = false; 1787b9c1b51eSKate Stone if (sc->function && sc->function->GetIsOptimized()) { 17886ab659a9SJason Molenda is_optimized = true; 17896ab659a9SJason Molenda } 17906ab659a9SJason Molenda return is_optimized; 17916ab659a9SJason Molenda } 17926ab659a9SJason Molenda 1793c980fa92SJason Molenda case Entry::Type::FunctionInitial: 1794a74f37a5SEugene Zelenko return initial_function; 1795c980fa92SJason Molenda 1796554f68d3SGreg Clayton case Entry::Type::LineEntryFile: 1797b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1798554f68d3SGreg Clayton Module *module = sc->module_sp.get(); 1799b9c1b51eSKate Stone if (module) { 1800554f68d3SGreg Clayton if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1801554f68d3SGreg Clayton return true; 1802554f68d3SGreg Clayton } 1803554f68d3SGreg Clayton } 1804554f68d3SGreg Clayton return false; 1805554f68d3SGreg Clayton 1806554f68d3SGreg Clayton case Entry::Type::LineEntryLineNumber: 1807b9c1b51eSKate Stone if (sc && sc->line_entry.IsValid()) { 1808554f68d3SGreg Clayton const char *format = "%" PRIu32; 1809554f68d3SGreg Clayton if (!entry.printf_format.empty()) 1810554f68d3SGreg Clayton format = entry.printf_format.c_str(); 1811554f68d3SGreg Clayton s.Printf(format, sc->line_entry.line); 1812554f68d3SGreg Clayton return true; 1813554f68d3SGreg Clayton } 1814554f68d3SGreg Clayton return false; 1815554f68d3SGreg Clayton 1816554f68d3SGreg Clayton case Entry::Type::LineEntryStartAddress: 1817554f68d3SGreg Clayton case Entry::Type::LineEntryEndAddress: 1818b9c1b51eSKate Stone if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { 1819554f68d3SGreg Clayton Address addr = sc->line_entry.range.GetBaseAddress(); 1820554f68d3SGreg Clayton 1821554f68d3SGreg Clayton if (entry.type == Entry::Type::LineEntryEndAddress) 1822554f68d3SGreg Clayton addr.Slide(sc->line_entry.range.GetByteSize()); 1823554f68d3SGreg Clayton if (DumpAddress(s, sc, exe_ctx, addr, false)) 1824554f68d3SGreg Clayton return true; 1825554f68d3SGreg Clayton } 1826554f68d3SGreg Clayton return false; 1827554f68d3SGreg Clayton 1828554f68d3SGreg Clayton case Entry::Type::CurrentPCArrow: 1829b9c1b51eSKate Stone if (addr && exe_ctx && exe_ctx->GetFramePtr()) { 1830b9c1b51eSKate Stone RegisterContextSP reg_ctx = 1831b9c1b51eSKate Stone exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1832b9c1b51eSKate Stone if (reg_ctx) { 1833554f68d3SGreg Clayton addr_t pc_loadaddr = reg_ctx->GetPC(); 1834b9c1b51eSKate Stone if (pc_loadaddr != LLDB_INVALID_ADDRESS) { 1835554f68d3SGreg Clayton Address pc; 1836554f68d3SGreg Clayton pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); 1837b9c1b51eSKate Stone if (pc == *addr) { 1838554f68d3SGreg Clayton s.Printf("-> "); 1839554f68d3SGreg Clayton return true; 1840554f68d3SGreg Clayton } 1841554f68d3SGreg Clayton } 1842554f68d3SGreg Clayton } 1843554f68d3SGreg Clayton s.Printf(" "); 1844554f68d3SGreg Clayton return true; 1845554f68d3SGreg Clayton } 1846554f68d3SGreg Clayton return false; 1847554f68d3SGreg Clayton } 1848554f68d3SGreg Clayton return false; 1849554f68d3SGreg Clayton } 1850554f68d3SGreg Clayton 1851b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames( 1852b9c1b51eSKate Stone Stream &s, const FormatEntity::Entry::Definition *parent) { 1853b9c1b51eSKate Stone if (parent->children) { 1854554f68d3SGreg Clayton const size_t n = parent->num_children; 1855b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1856554f68d3SGreg Clayton if (i > 0) 1857554f68d3SGreg Clayton s.PutCString(", "); 1858554f68d3SGreg Clayton s.Printf("\"%s\"", parent->children[i].name); 1859554f68d3SGreg Clayton } 1860554f68d3SGreg Clayton return true; 1861554f68d3SGreg Clayton } 1862554f68d3SGreg Clayton return false; 1863554f68d3SGreg Clayton } 1864554f68d3SGreg Clayton 186597206d57SZachary Turner static Status ParseEntry(const llvm::StringRef &format_str, 1866554f68d3SGreg Clayton const FormatEntity::Entry::Definition *parent, 1867b9c1b51eSKate Stone FormatEntity::Entry &entry) { 186897206d57SZachary Turner Status error; 1869554f68d3SGreg Clayton 1870554f68d3SGreg Clayton const size_t sep_pos = format_str.find_first_of(".[:"); 1871b9c1b51eSKate Stone const char sep_char = 1872b9c1b51eSKate Stone (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1873554f68d3SGreg Clayton llvm::StringRef key = format_str.substr(0, sep_pos); 1874554f68d3SGreg Clayton 1875554f68d3SGreg Clayton const size_t n = parent->num_children; 1876b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1877554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1878b9c1b51eSKate Stone if (key.equals(entry_def->name) || entry_def->name[0] == '*') { 1879554f68d3SGreg Clayton llvm::StringRef value; 1880554f68d3SGreg Clayton if (sep_char) 1881b9c1b51eSKate Stone value = 1882b9c1b51eSKate Stone format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1883b9c1b51eSKate Stone switch (entry_def->type) { 1884554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentString: 18853a29f8b9SPavel Labath entry.string = format_str.str(); 1886554f68d3SGreg Clayton return error; // Success 1887554f68d3SGreg Clayton 1888554f68d3SGreg Clayton case FormatEntity::Entry::Type::ParentNumber: 1889554f68d3SGreg Clayton entry.number = entry_def->data; 1890554f68d3SGreg Clayton return error; // Success 1891554f68d3SGreg Clayton 1892554f68d3SGreg Clayton case FormatEntity::Entry::Type::InsertString: 1893554f68d3SGreg Clayton entry.type = entry_def->type; 1894554f68d3SGreg Clayton entry.string = entry_def->string; 1895554f68d3SGreg Clayton return error; // Success 1896554f68d3SGreg Clayton 1897554f68d3SGreg Clayton default: 1898554f68d3SGreg Clayton entry.type = entry_def->type; 1899554f68d3SGreg Clayton break; 1900554f68d3SGreg Clayton } 1901554f68d3SGreg Clayton 1902b9c1b51eSKate Stone if (value.empty()) { 1903b9c1b51eSKate Stone if (entry_def->type == FormatEntity::Entry::Type::Invalid) { 1904b9c1b51eSKate Stone if (entry_def->children) { 1905554f68d3SGreg Clayton StreamString error_strm; 1906b9c1b51eSKate Stone error_strm.Printf("'%s' can't be specified on its own, you must " 1907b9c1b51eSKate Stone "access one of its children: ", 1908b9c1b51eSKate Stone entry_def->name); 1909554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, entry_def); 1910c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1911b9c1b51eSKate Stone } else if (sep_char == ':') { 1912b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 191305097246SAdrian Prantl // string argument that needs to be stored in the entry (like 191405097246SAdrian Prantl // "${script.var:}"). In this case the string value is the empty 191505097246SAdrian Prantl // string which is ok. 1916b9c1b51eSKate Stone } else { 1917554f68d3SGreg Clayton error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1918554f68d3SGreg Clayton } 1919554f68d3SGreg Clayton } 1920b9c1b51eSKate Stone } else { 1921b9c1b51eSKate Stone if (entry_def->children) { 1922554f68d3SGreg Clayton error = ParseEntry(value, entry_def, entry); 1923b9c1b51eSKate Stone } else if (sep_char == ':') { 1924b9c1b51eSKate Stone // Any value whose separator is a with a ':' means this value has a 192505097246SAdrian Prantl // string argument that needs to be stored in the entry (like 1926b9c1b51eSKate Stone // "${script.var:modulename.function}") 19273a29f8b9SPavel Labath entry.string = value.str(); 1928b9c1b51eSKate Stone } else { 1929b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1930b9c1b51eSKate Stone "'%s' followed by '%s' but it has no children", key.str().c_str(), 1931554f68d3SGreg Clayton value.str().c_str()); 1932554f68d3SGreg Clayton } 1933554f68d3SGreg Clayton } 1934554f68d3SGreg Clayton return error; 1935554f68d3SGreg Clayton } 1936554f68d3SGreg Clayton } 1937554f68d3SGreg Clayton StreamString error_strm; 1938554f68d3SGreg Clayton if (parent->type == FormatEntity::Entry::Type::Root) 1939b9c1b51eSKate Stone error_strm.Printf( 1940b9c1b51eSKate Stone "invalid top level item '%s'. Valid top level items are: ", 1941b9c1b51eSKate Stone key.str().c_str()); 1942554f68d3SGreg Clayton else 1943b9c1b51eSKate Stone error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", 1944b9c1b51eSKate Stone key.str().c_str(), parent->name); 1945554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames(error_strm, parent); 1946c156427dSZachary Turner error.SetErrorStringWithFormat("%s", error_strm.GetData()); 1947554f68d3SGreg Clayton return error; 1948554f68d3SGreg Clayton } 1949554f68d3SGreg Clayton 1950554f68d3SGreg Clayton static const FormatEntity::Entry::Definition * 1951b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str, 1952b9c1b51eSKate Stone const FormatEntity::Entry::Definition *parent, 1953b9c1b51eSKate Stone llvm::StringRef &remainder) { 195497206d57SZachary Turner Status error; 1955554f68d3SGreg Clayton 1956554f68d3SGreg Clayton std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 1957554f68d3SGreg Clayton const size_t n = parent->num_children; 1958b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 1959554f68d3SGreg Clayton const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1960b9c1b51eSKate Stone if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { 1961b9c1b51eSKate Stone if (p.second.empty()) { 1962554f68d3SGreg Clayton if (format_str.back() == '.') 1963554f68d3SGreg Clayton remainder = format_str.drop_front(format_str.size() - 1); 1964554f68d3SGreg Clayton else 1965554f68d3SGreg Clayton remainder = llvm::StringRef(); // Exact match 1966554f68d3SGreg Clayton return entry_def; 1967b9c1b51eSKate Stone } else { 1968b9c1b51eSKate Stone if (entry_def->children) { 1969554f68d3SGreg Clayton return FindEntry(p.second, entry_def, remainder); 1970b9c1b51eSKate Stone } else { 1971554f68d3SGreg Clayton remainder = p.second; 1972554f68d3SGreg Clayton return entry_def; 1973554f68d3SGreg Clayton } 1974554f68d3SGreg Clayton } 1975554f68d3SGreg Clayton } 1976554f68d3SGreg Clayton } 1977554f68d3SGreg Clayton remainder = format_str; 1978554f68d3SGreg Clayton return parent; 1979554f68d3SGreg Clayton } 1980554f68d3SGreg Clayton 198197206d57SZachary Turner Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, 1982b9c1b51eSKate Stone uint32_t depth) { 198397206d57SZachary Turner Status error; 1984b9c1b51eSKate Stone while (!format.empty() && error.Success()) { 1985554f68d3SGreg Clayton const size_t non_special_chars = format.find_first_of("${}\\"); 1986554f68d3SGreg Clayton 1987b9c1b51eSKate Stone if (non_special_chars == llvm::StringRef::npos) { 1988554f68d3SGreg Clayton // No special characters, just string bytes so add them and we are done 1989554f68d3SGreg Clayton parent_entry.AppendText(format); 1990554f68d3SGreg Clayton return error; 1991554f68d3SGreg Clayton } 1992554f68d3SGreg Clayton 1993b9c1b51eSKate Stone if (non_special_chars > 0) { 1994b9c1b51eSKate Stone // We have a special character, so add all characters before these as a 1995b9c1b51eSKate Stone // plain string 1996554f68d3SGreg Clayton parent_entry.AppendText(format.substr(0, non_special_chars)); 1997554f68d3SGreg Clayton format = format.drop_front(non_special_chars); 1998554f68d3SGreg Clayton } 1999554f68d3SGreg Clayton 2000b9c1b51eSKate Stone switch (format[0]) { 2001554f68d3SGreg Clayton case '\0': 2002554f68d3SGreg Clayton return error; 2003554f68d3SGreg Clayton 2004b9c1b51eSKate Stone case '{': { 2005554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2006554f68d3SGreg Clayton Entry scope_entry(Entry::Type::Scope); 2007554f68d3SGreg Clayton error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); 2008554f68d3SGreg Clayton if (error.Fail()) 2009554f68d3SGreg Clayton return error; 2010554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(scope_entry)); 2011b9c1b51eSKate Stone } break; 2012554f68d3SGreg Clayton 2013554f68d3SGreg Clayton case '}': 2014554f68d3SGreg Clayton if (depth == 0) 2015554f68d3SGreg Clayton error.SetErrorString("unmatched '}' character"); 2016554f68d3SGreg Clayton else 2017b9c1b51eSKate Stone format = 2018b9c1b51eSKate Stone format 2019b9c1b51eSKate Stone .drop_front(); // Skip the '}' as we are at the end of the scope 2020554f68d3SGreg Clayton return error; 2021554f68d3SGreg Clayton 2022b9c1b51eSKate Stone case '\\': { 2023554f68d3SGreg Clayton format = format.drop_front(); // Skip the '\' character 2024b9c1b51eSKate Stone if (format.empty()) { 2025b9c1b51eSKate Stone error.SetErrorString( 2026b9c1b51eSKate Stone "'\\' character was not followed by another character"); 2027554f68d3SGreg Clayton return error; 2028554f68d3SGreg Clayton } 2029554f68d3SGreg Clayton 2030554f68d3SGreg Clayton const char desens_char = format[0]; 2031554f68d3SGreg Clayton format = format.drop_front(); // Skip the desensitized char character 2032b9c1b51eSKate Stone switch (desens_char) { 2033b9c1b51eSKate Stone case 'a': 2034b9c1b51eSKate Stone parent_entry.AppendChar('\a'); 2035b9c1b51eSKate Stone break; 2036b9c1b51eSKate Stone case 'b': 2037b9c1b51eSKate Stone parent_entry.AppendChar('\b'); 2038b9c1b51eSKate Stone break; 2039b9c1b51eSKate Stone case 'f': 2040b9c1b51eSKate Stone parent_entry.AppendChar('\f'); 2041b9c1b51eSKate Stone break; 2042b9c1b51eSKate Stone case 'n': 2043b9c1b51eSKate Stone parent_entry.AppendChar('\n'); 2044b9c1b51eSKate Stone break; 2045b9c1b51eSKate Stone case 'r': 2046b9c1b51eSKate Stone parent_entry.AppendChar('\r'); 2047b9c1b51eSKate Stone break; 2048b9c1b51eSKate Stone case 't': 2049b9c1b51eSKate Stone parent_entry.AppendChar('\t'); 2050b9c1b51eSKate Stone break; 2051b9c1b51eSKate Stone case 'v': 2052b9c1b51eSKate Stone parent_entry.AppendChar('\v'); 2053b9c1b51eSKate Stone break; 2054b9c1b51eSKate Stone case '\'': 2055b9c1b51eSKate Stone parent_entry.AppendChar('\''); 2056b9c1b51eSKate Stone break; 2057b9c1b51eSKate Stone case '\\': 2058b9c1b51eSKate Stone parent_entry.AppendChar('\\'); 2059b9c1b51eSKate Stone break; 2060554f68d3SGreg Clayton case '0': 2061554f68d3SGreg Clayton // 1 to 3 octal chars 2062554f68d3SGreg Clayton { 206305097246SAdrian Prantl // Make a string that can hold onto the initial zero char, up to 3 206405097246SAdrian Prantl // octal digits, and a terminating NULL. 2065554f68d3SGreg Clayton char oct_str[5] = {0, 0, 0, 0, 0}; 2066554f68d3SGreg Clayton 2067554f68d3SGreg Clayton int i; 2068554f68d3SGreg Clayton for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) 2069554f68d3SGreg Clayton oct_str[i] = format[i]; 2070554f68d3SGreg Clayton 207105097246SAdrian Prantl // We don't want to consume the last octal character since the main 207205097246SAdrian Prantl // for loop will do this for us, so we advance p by one less than i 207305097246SAdrian Prantl // (even if i is zero) 2074554f68d3SGreg Clayton format = format.drop_front(i); 2075a74f37a5SEugene Zelenko unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); 2076b9c1b51eSKate Stone if (octal_value <= UINT8_MAX) { 2077554f68d3SGreg Clayton parent_entry.AppendChar((char)octal_value); 2078b9c1b51eSKate Stone } else { 2079554f68d3SGreg Clayton error.SetErrorString("octal number is larger than a single byte"); 2080554f68d3SGreg Clayton return error; 2081554f68d3SGreg Clayton } 2082554f68d3SGreg Clayton } 2083554f68d3SGreg Clayton break; 2084554f68d3SGreg Clayton 2085554f68d3SGreg Clayton case 'x': 2086554f68d3SGreg Clayton // hex number in the format 2087b9c1b51eSKate Stone if (isxdigit(format[0])) { 2088554f68d3SGreg Clayton // Make a string that can hold onto two hex chars plus a 2089554f68d3SGreg Clayton // NULL terminator 2090554f68d3SGreg Clayton char hex_str[3] = {0, 0, 0}; 2091554f68d3SGreg Clayton hex_str[0] = format[0]; 2092554f68d3SGreg Clayton 2093554f68d3SGreg Clayton format = format.drop_front(); 2094554f68d3SGreg Clayton 2095b9c1b51eSKate Stone if (isxdigit(format[0])) { 2096554f68d3SGreg Clayton hex_str[1] = format[0]; 2097554f68d3SGreg Clayton format = format.drop_front(); 2098554f68d3SGreg Clayton } 2099554f68d3SGreg Clayton 2100a74f37a5SEugene Zelenko unsigned long hex_value = strtoul(hex_str, nullptr, 16); 2101b9c1b51eSKate Stone if (hex_value <= UINT8_MAX) { 2102554f68d3SGreg Clayton parent_entry.AppendChar((char)hex_value); 2103b9c1b51eSKate Stone } else { 2104554f68d3SGreg Clayton error.SetErrorString("hex number is larger than a single byte"); 2105554f68d3SGreg Clayton return error; 2106554f68d3SGreg Clayton } 2107b9c1b51eSKate Stone } else { 2108554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2109554f68d3SGreg Clayton } 2110554f68d3SGreg Clayton break; 2111554f68d3SGreg Clayton 2112554f68d3SGreg Clayton default: 211305097246SAdrian Prantl // Just desensitize any other character by just printing what came 211405097246SAdrian Prantl // after the '\' 2115554f68d3SGreg Clayton parent_entry.AppendChar(desens_char); 2116554f68d3SGreg Clayton break; 2117554f68d3SGreg Clayton } 2118b9c1b51eSKate Stone } break; 2119554f68d3SGreg Clayton 2120554f68d3SGreg Clayton case '$': 2121b9c1b51eSKate Stone if (format.size() == 1) { 2122554f68d3SGreg Clayton // '$' at the end of a format string, just print the '$' 2123554f68d3SGreg Clayton parent_entry.AppendText("$"); 2124b9c1b51eSKate Stone } else { 2125554f68d3SGreg Clayton format = format.drop_front(); // Skip the '$' 2126554f68d3SGreg Clayton 2127b9c1b51eSKate Stone if (format[0] == '{') { 2128554f68d3SGreg Clayton format = format.drop_front(); // Skip the '{' 2129554f68d3SGreg Clayton 2130554f68d3SGreg Clayton llvm::StringRef variable, variable_format; 2131b9c1b51eSKate Stone error = FormatEntity::ExtractVariableInfo(format, variable, 2132b9c1b51eSKate Stone variable_format); 2133554f68d3SGreg Clayton if (error.Fail()) 2134554f68d3SGreg Clayton return error; 2135554f68d3SGreg Clayton bool verify_is_thread_id = false; 2136554f68d3SGreg Clayton Entry entry; 2137b9c1b51eSKate Stone if (!variable_format.empty()) { 21383a29f8b9SPavel Labath entry.printf_format = variable_format.str(); 2139554f68d3SGreg Clayton 214005097246SAdrian Prantl // If the format contains a '%' we are going to assume this is a 214105097246SAdrian Prantl // printf style format. So if you want to format your thread ID 214205097246SAdrian Prantl // using "0x%llx" you can use: ${thread.id%0x%llx} 2143554f68d3SGreg Clayton // 2144554f68d3SGreg Clayton // If there is no '%' in the format, then it is assumed to be a 2145554f68d3SGreg Clayton // LLDB format name, or one of the extended formats specified in 2146554f68d3SGreg Clayton // the switch statement below. 2147554f68d3SGreg Clayton 2148b9c1b51eSKate Stone if (entry.printf_format.find('%') == std::string::npos) { 2149554f68d3SGreg Clayton bool clear_printf = false; 2150554f68d3SGreg Clayton 2151b9c1b51eSKate Stone if (FormatManager::GetFormatFromCString( 2152b9c1b51eSKate Stone entry.printf_format.c_str(), false, entry.fmt)) { 2153554f68d3SGreg Clayton // We have an LLDB format, so clear the printf format 2154554f68d3SGreg Clayton clear_printf = true; 2155b9c1b51eSKate Stone } else if (entry.printf_format.size() == 1) { 2156b9c1b51eSKate Stone switch (entry.printf_format[0]) { 2157554f68d3SGreg Clayton case '@': // if this is an @ sign, print ObjC description 2158b9c1b51eSKate Stone entry.number = ValueObject:: 2159b9c1b51eSKate Stone eValueObjectRepresentationStyleLanguageSpecific; 2160554f68d3SGreg Clayton clear_printf = true; 2161554f68d3SGreg Clayton break; 2162b9c1b51eSKate Stone case 'V': // if this is a V, print the value using the default 2163b9c1b51eSKate Stone // format 2164b9c1b51eSKate Stone entry.number = 2165b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2166554f68d3SGreg Clayton clear_printf = true; 2167554f68d3SGreg Clayton break; 2168554f68d3SGreg Clayton case 'L': // if this is an L, print the location of the value 2169b9c1b51eSKate Stone entry.number = 2170b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleLocation; 2171554f68d3SGreg Clayton clear_printf = true; 2172554f68d3SGreg Clayton break; 2173554f68d3SGreg Clayton case 'S': // if this is an S, print the summary after all 2174b9c1b51eSKate Stone entry.number = 2175b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2176554f68d3SGreg Clayton clear_printf = true; 2177554f68d3SGreg Clayton break; 2178554f68d3SGreg Clayton case '#': // if this is a '#', print the number of children 2179b9c1b51eSKate Stone entry.number = 2180b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleChildrenCount; 2181554f68d3SGreg Clayton clear_printf = true; 2182554f68d3SGreg Clayton break; 2183554f68d3SGreg Clayton case 'T': // if this is a 'T', print the type 2184b9c1b51eSKate Stone entry.number = 2185b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleType; 2186554f68d3SGreg Clayton clear_printf = true; 2187554f68d3SGreg Clayton break; 2188554f68d3SGreg Clayton case 'N': // if this is a 'N', print the name 2189b9c1b51eSKate Stone entry.number = 2190b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleName; 2191554f68d3SGreg Clayton clear_printf = true; 2192554f68d3SGreg Clayton break; 2193281b65bcSGreg Clayton case '>': // if this is a '>', print the expression path 2194b9c1b51eSKate Stone entry.number = ValueObject:: 2195b9c1b51eSKate Stone eValueObjectRepresentationStyleExpressionPath; 2196554f68d3SGreg Clayton clear_printf = true; 2197554f68d3SGreg Clayton break; 2198554f68d3SGreg Clayton default: 2199b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2200b9c1b51eSKate Stone entry.printf_format.c_str()); 2201554f68d3SGreg Clayton return error; 2202554f68d3SGreg Clayton } 2203b9c1b51eSKate Stone } else if (FormatManager::GetFormatFromCString( 2204b9c1b51eSKate Stone entry.printf_format.c_str(), true, entry.fmt)) { 2205554f68d3SGreg Clayton clear_printf = true; 2206b9c1b51eSKate Stone } else if (entry.printf_format == "tid") { 2207554f68d3SGreg Clayton verify_is_thread_id = true; 2208b9c1b51eSKate Stone } else { 2209b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid format: '%s'", 2210b9c1b51eSKate Stone entry.printf_format.c_str()); 2211554f68d3SGreg Clayton return error; 2212554f68d3SGreg Clayton } 2213554f68d3SGreg Clayton 2214554f68d3SGreg Clayton // Our format string turned out to not be a printf style format 2215554f68d3SGreg Clayton // so lets clear the string 2216554f68d3SGreg Clayton if (clear_printf) 2217554f68d3SGreg Clayton entry.printf_format.clear(); 2218554f68d3SGreg Clayton } 2219554f68d3SGreg Clayton } 2220554f68d3SGreg Clayton 2221554f68d3SGreg Clayton // Check for dereferences 2222b9c1b51eSKate Stone if (variable[0] == '*') { 2223554f68d3SGreg Clayton entry.deref = true; 2224554f68d3SGreg Clayton variable = variable.drop_front(); 2225554f68d3SGreg Clayton } 2226554f68d3SGreg Clayton 2227554f68d3SGreg Clayton error = ParseEntry(variable, &g_root, entry); 2228554f68d3SGreg Clayton if (error.Fail()) 2229554f68d3SGreg Clayton return error; 2230554f68d3SGreg Clayton 2231b9c1b51eSKate Stone if (verify_is_thread_id) { 2232554f68d3SGreg Clayton if (entry.type != Entry::Type::ThreadID && 2233b9c1b51eSKate Stone entry.type != Entry::Type::ThreadProtocolID) { 2234b9c1b51eSKate Stone error.SetErrorString("the 'tid' format can only be used on " 2235b9c1b51eSKate Stone "${thread.id} and ${thread.protocol_id}"); 2236554f68d3SGreg Clayton } 2237554f68d3SGreg Clayton } 2238554f68d3SGreg Clayton 2239b9c1b51eSKate Stone switch (entry.type) { 2240554f68d3SGreg Clayton case Entry::Type::Variable: 2241554f68d3SGreg Clayton case Entry::Type::VariableSynthetic: 2242b9c1b51eSKate Stone if (entry.number == 0) { 2243554f68d3SGreg Clayton if (entry.string.empty()) 2244b9c1b51eSKate Stone entry.number = 2245b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleValue; 2246554f68d3SGreg Clayton else 2247b9c1b51eSKate Stone entry.number = 2248b9c1b51eSKate Stone ValueObject::eValueObjectRepresentationStyleSummary; 2249554f68d3SGreg Clayton } 2250554f68d3SGreg Clayton break; 2251554f68d3SGreg Clayton default: 2252b9c1b51eSKate Stone // Make sure someone didn't try to dereference anything but ${var} 2253b9c1b51eSKate Stone // or ${svar} 2254b9c1b51eSKate Stone if (entry.deref) { 2255b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2256b9c1b51eSKate Stone "${%s} can't be dereferenced, only ${var} and ${svar} can.", 2257b9c1b51eSKate Stone variable.str().c_str()); 2258554f68d3SGreg Clayton return error; 2259554f68d3SGreg Clayton } 2260554f68d3SGreg Clayton } 226105097246SAdrian Prantl // Check if this entry just wants to insert a constant string value 226205097246SAdrian Prantl // into the parent_entry, if so, insert the string with AppendText, 226305097246SAdrian Prantl // else append the entry to the parent_entry. 2264554f68d3SGreg Clayton if (entry.type == Entry::Type::InsertString) 2265554f68d3SGreg Clayton parent_entry.AppendText(entry.string.c_str()); 2266554f68d3SGreg Clayton else 2267554f68d3SGreg Clayton parent_entry.AppendEntry(std::move(entry)); 2268554f68d3SGreg Clayton } 2269554f68d3SGreg Clayton } 2270554f68d3SGreg Clayton break; 2271554f68d3SGreg Clayton } 2272554f68d3SGreg Clayton } 2273554f68d3SGreg Clayton return error; 2274554f68d3SGreg Clayton } 2275554f68d3SGreg Clayton 227697206d57SZachary Turner Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, 2277b9c1b51eSKate Stone llvm::StringRef &variable_name, 2278b9c1b51eSKate Stone llvm::StringRef &variable_format) { 227997206d57SZachary Turner Status error; 2280554f68d3SGreg Clayton variable_name = llvm::StringRef(); 2281554f68d3SGreg Clayton variable_format = llvm::StringRef(); 2282554f68d3SGreg Clayton 2283e8433cc1SBruce Mitchener const size_t paren_pos = format_str.find('}'); 2284b9c1b51eSKate Stone if (paren_pos != llvm::StringRef::npos) { 2285e8433cc1SBruce Mitchener const size_t percent_pos = format_str.find('%'); 2286b9c1b51eSKate Stone if (percent_pos < paren_pos) { 2287b9c1b51eSKate Stone if (percent_pos > 0) { 2288554f68d3SGreg Clayton if (percent_pos > 1) 2289554f68d3SGreg Clayton variable_name = format_str.substr(0, percent_pos); 2290b9c1b51eSKate Stone variable_format = 2291b9c1b51eSKate Stone format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2292554f68d3SGreg Clayton } 2293b9c1b51eSKate Stone } else { 2294554f68d3SGreg Clayton variable_name = format_str.substr(0, paren_pos); 2295554f68d3SGreg Clayton } 2296554f68d3SGreg Clayton // Strip off elements and the formatting and the trailing '}' 2297554f68d3SGreg Clayton format_str = format_str.substr(paren_pos + 1); 2298b9c1b51eSKate Stone } else { 2299b9c1b51eSKate Stone error.SetErrorStringWithFormat( 2300b9c1b51eSKate Stone "missing terminating '}' character for '${%s'", 2301b9c1b51eSKate Stone format_str.str().c_str()); 2302554f68d3SGreg Clayton } 2303554f68d3SGreg Clayton return error; 2304554f68d3SGreg Clayton } 2305554f68d3SGreg Clayton 2306b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, 2307b9c1b51eSKate Stone llvm::StringRef variable_name, 2308b9c1b51eSKate Stone llvm::StringRef variable_format) { 2309b9c1b51eSKate Stone if (variable_name.empty() || variable_name.equals(".fullpath")) { 2310554f68d3SGreg Clayton file_spec.Dump(&s); 2311554f68d3SGreg Clayton return true; 2312b9c1b51eSKate Stone } else if (variable_name.equals(".basename")) { 2313554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2314554f68d3SGreg Clayton return true; 2315b9c1b51eSKate Stone } else if (variable_name.equals(".dirname")) { 2316554f68d3SGreg Clayton s.PutCString(file_spec.GetFilename().AsCString("")); 2317554f68d3SGreg Clayton return true; 2318554f68d3SGreg Clayton } 2319554f68d3SGreg Clayton return false; 2320554f68d3SGreg Clayton } 2321554f68d3SGreg Clayton 2322b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix, 2323b9c1b51eSKate Stone const char *suffix) { 2324554f68d3SGreg Clayton std::string match(prefix.str()); 2325554f68d3SGreg Clayton match.append(suffix); 23263a29f8b9SPavel Labath return match; 2327554f68d3SGreg Clayton } 2328554f68d3SGreg Clayton 2329b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def, 2330554f68d3SGreg Clayton const llvm::StringRef &prefix, 2331554f68d3SGreg Clayton const llvm::StringRef &match_prefix, 2332b9c1b51eSKate Stone StringList &matches) { 2333554f68d3SGreg Clayton const size_t n = def->num_children; 2334b9c1b51eSKate Stone if (n > 0) { 2335b9c1b51eSKate Stone for (size_t i = 0; i < n; ++i) { 23363a29f8b9SPavel Labath std::string match = prefix.str(); 2337554f68d3SGreg Clayton if (match_prefix.empty()) 2338554f68d3SGreg Clayton matches.AppendString(MakeMatch(prefix, def->children[i].name)); 2339b9c1b51eSKate Stone else if (strncmp(def->children[i].name, match_prefix.data(), 2340b9c1b51eSKate Stone match_prefix.size()) == 0) 2341b9c1b51eSKate Stone matches.AppendString( 2342b9c1b51eSKate Stone MakeMatch(prefix, def->children[i].name + match_prefix.size())); 2343554f68d3SGreg Clayton } 2344554f68d3SGreg Clayton } 2345554f68d3SGreg Clayton } 2346a74f37a5SEugene Zelenko 2347*a2e76c0bSRaphael Isemann size_t FormatEntity::AutoComplete(CompletionRequest &request) { 2348*a2e76c0bSRaphael Isemann llvm::StringRef str = request.GetCursorArgumentPrefix().str(); 2349*a2e76c0bSRaphael Isemann 2350*a2e76c0bSRaphael Isemann request.SetWordComplete(false); 2351*a2e76c0bSRaphael Isemann str = str.drop_front(request.GetMatchStartPoint()); 2352*a2e76c0bSRaphael Isemann request.GetMatches().Clear(); 2353554f68d3SGreg Clayton 2354554f68d3SGreg Clayton const size_t dollar_pos = str.rfind('$'); 23554aa8753cSZachary Turner if (dollar_pos == llvm::StringRef::npos) 23564aa8753cSZachary Turner return 0; 23574aa8753cSZachary Turner 2358554f68d3SGreg Clayton // Hitting TAB after $ at the end of the string add a "{" 2359b9c1b51eSKate Stone if (dollar_pos == str.size() - 1) { 23603a29f8b9SPavel Labath std::string match = str.str(); 2361554f68d3SGreg Clayton match.append("{"); 2362*a2e76c0bSRaphael Isemann request.GetMatches().AppendString(match); 23634aa8753cSZachary Turner return 1; 23644aa8753cSZachary Turner } 23654aa8753cSZachary Turner 23664aa8753cSZachary Turner if (str[dollar_pos + 1] != '{') 23674aa8753cSZachary Turner return 0; 23684aa8753cSZachary Turner 2369554f68d3SGreg Clayton const size_t close_pos = str.find('}', dollar_pos + 2); 23704aa8753cSZachary Turner if (close_pos != llvm::StringRef::npos) 23714aa8753cSZachary Turner return 0; 23724aa8753cSZachary Turner 2373554f68d3SGreg Clayton const size_t format_pos = str.find('%', dollar_pos + 2); 23744aa8753cSZachary Turner if (format_pos != llvm::StringRef::npos) 23754aa8753cSZachary Turner return 0; 23764aa8753cSZachary Turner 2377554f68d3SGreg Clayton llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); 2378b9c1b51eSKate Stone if (partial_variable.empty()) { 2379554f68d3SGreg Clayton // Suggest all top level entites as we are just past "${" 2380*a2e76c0bSRaphael Isemann AddMatches(&g_root, str, llvm::StringRef(), request.GetMatches()); 2381*a2e76c0bSRaphael Isemann return request.GetMatches().GetSize(); 23824aa8753cSZachary Turner } 23834aa8753cSZachary Turner 2384554f68d3SGreg Clayton // We have a partially specified variable, find it 2385554f68d3SGreg Clayton llvm::StringRef remainder; 2386b9c1b51eSKate Stone const FormatEntity::Entry::Definition *entry_def = 2387b9c1b51eSKate Stone FindEntry(partial_variable, &g_root, remainder); 23884aa8753cSZachary Turner if (!entry_def) 23894aa8753cSZachary Turner return 0; 23904aa8753cSZachary Turner 2391554f68d3SGreg Clayton const size_t n = entry_def->num_children; 2392554f68d3SGreg Clayton 2393b9c1b51eSKate Stone if (remainder.empty()) { 2394554f68d3SGreg Clayton // Exact match 2395b9c1b51eSKate Stone if (n > 0) { 2396554f68d3SGreg Clayton // "${thread.info" <TAB> 2397*a2e76c0bSRaphael Isemann request.GetMatches().AppendString(MakeMatch(str, ".")); 2398b9c1b51eSKate Stone } else { 2399554f68d3SGreg Clayton // "${thread.id" <TAB> 2400*a2e76c0bSRaphael Isemann request.GetMatches().AppendString(MakeMatch(str, "}")); 2401*a2e76c0bSRaphael Isemann request.SetWordComplete(true); 2402554f68d3SGreg Clayton } 2403b9c1b51eSKate Stone } else if (remainder.equals(".")) { 2404554f68d3SGreg Clayton // "${thread." <TAB> 2405*a2e76c0bSRaphael Isemann AddMatches(entry_def, str, llvm::StringRef(), request.GetMatches()); 2406b9c1b51eSKate Stone } else { 2407554f68d3SGreg Clayton // We have a partial match 2408554f68d3SGreg Clayton // "${thre" <TAB> 2409*a2e76c0bSRaphael Isemann AddMatches(entry_def, str, remainder, request.GetMatches()); 2410554f68d3SGreg Clayton } 2411*a2e76c0bSRaphael Isemann return request.GetMatches().GetSize(); 2412554f68d3SGreg Clayton } 2413