1 //===-- TypeSummary.cpp ---------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/DataFormatters/TypeSummary.h" 10 11 12 13 14 #include "lldb/lldb-enumerations.h" 15 #include "lldb/lldb-public.h" 16 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/ValueObject.h" 19 #include "lldb/DataFormatters/ValueObjectPrinter.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Symbol/CompilerType.h" 22 #include "lldb/Target/StackFrame.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Utility/StreamString.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 TypeSummaryOptions::TypeSummaryOptions() = default; 30 31 lldb::LanguageType TypeSummaryOptions::GetLanguage() const { return m_lang; } 32 33 lldb::TypeSummaryCapping TypeSummaryOptions::GetCapping() const { 34 return m_capping; 35 } 36 37 TypeSummaryOptions &TypeSummaryOptions::SetLanguage(lldb::LanguageType lang) { 38 m_lang = lang; 39 return *this; 40 } 41 42 TypeSummaryOptions & 43 TypeSummaryOptions::SetCapping(lldb::TypeSummaryCapping cap) { 44 m_capping = cap; 45 return *this; 46 } 47 48 TypeSummaryImpl::TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags) 49 : m_flags(flags), m_kind(kind) {} 50 51 StringSummaryFormat::StringSummaryFormat(const TypeSummaryImpl::Flags &flags, 52 const char *format_cstr) 53 : TypeSummaryImpl(Kind::eSummaryString, flags), m_format_str() { 54 SetSummaryString(format_cstr); 55 } 56 57 void StringSummaryFormat::SetSummaryString(const char *format_cstr) { 58 m_format.Clear(); 59 if (format_cstr && format_cstr[0]) { 60 m_format_str = format_cstr; 61 m_error = FormatEntity::Parse(format_cstr, m_format); 62 } else { 63 m_format_str.clear(); 64 m_error.Clear(); 65 } 66 } 67 68 bool StringSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval, 69 const TypeSummaryOptions &options) { 70 if (!valobj) { 71 retval.assign("NULL ValueObject"); 72 return false; 73 } 74 75 StreamString s; 76 ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); 77 SymbolContext sc; 78 StackFrame *frame = exe_ctx.GetFramePtr(); 79 if (frame) 80 sc = frame->GetSymbolContext(lldb::eSymbolContextEverything); 81 82 if (IsOneLiner()) { 83 ValueObjectPrinter printer(valobj, &s, DumpValueObjectOptions()); 84 printer.PrintChildrenOneLiner(HideNames(valobj)); 85 retval = std::string(s.GetString()); 86 return true; 87 } else { 88 if (FormatEntity::Format(m_format, s, &sc, &exe_ctx, 89 &sc.line_entry.range.GetBaseAddress(), valobj, 90 false, false)) { 91 retval.assign(std::string(s.GetString())); 92 return true; 93 } else { 94 retval.assign("error: summary string parsing error"); 95 return false; 96 } 97 } 98 } 99 100 std::string StringSummaryFormat::GetDescription() { 101 StreamString sstr; 102 103 sstr.Printf("`%s`%s%s%s%s%s%s%s%s%s", m_format_str.c_str(), 104 m_error.Fail() ? " error: " : "", 105 m_error.Fail() ? m_error.AsCString() : "", 106 Cascades() ? "" : " (not cascading)", 107 !DoesPrintChildren(nullptr) ? "" : " (show children)", 108 !DoesPrintValue(nullptr) ? " (hide value)" : "", 109 IsOneLiner() ? " (one-line printout)" : "", 110 SkipsPointers() ? " (skip pointers)" : "", 111 SkipsReferences() ? " (skip references)" : "", 112 HideNames(nullptr) ? " (hide member names)" : ""); 113 return std::string(sstr.GetString()); 114 } 115 116 CXXFunctionSummaryFormat::CXXFunctionSummaryFormat( 117 const TypeSummaryImpl::Flags &flags, Callback impl, const char *description) 118 : TypeSummaryImpl(Kind::eCallback, flags), m_impl(impl), 119 m_description(description ? description : "") {} 120 121 bool CXXFunctionSummaryFormat::FormatObject(ValueObject *valobj, 122 std::string &dest, 123 const TypeSummaryOptions &options) { 124 dest.clear(); 125 StreamString stream; 126 if (!m_impl || !m_impl(*valobj, stream, options)) 127 return false; 128 dest = std::string(stream.GetString()); 129 return true; 130 } 131 132 std::string CXXFunctionSummaryFormat::GetDescription() { 133 StreamString sstr; 134 sstr.Printf("%s%s%s%s%s%s%s %s", Cascades() ? "" : " (not cascading)", 135 !DoesPrintChildren(nullptr) ? "" : " (show children)", 136 !DoesPrintValue(nullptr) ? " (hide value)" : "", 137 IsOneLiner() ? " (one-line printout)" : "", 138 SkipsPointers() ? " (skip pointers)" : "", 139 SkipsReferences() ? " (skip references)" : "", 140 HideNames(nullptr) ? " (hide member names)" : "", 141 m_description.c_str()); 142 return std::string(sstr.GetString()); 143 } 144 145 ScriptSummaryFormat::ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags, 146 const char *function_name, 147 const char *python_script) 148 : TypeSummaryImpl(Kind::eScript, flags), m_function_name(), 149 m_python_script(), m_script_function_sp() { 150 if (function_name) 151 m_function_name.assign(function_name); 152 if (python_script) 153 m_python_script.assign(python_script); 154 } 155 156 bool ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval, 157 const TypeSummaryOptions &options) { 158 if (!valobj) 159 return false; 160 161 TargetSP target_sp(valobj->GetTargetSP()); 162 163 if (!target_sp) { 164 retval.assign("error: no target"); 165 return false; 166 } 167 168 ScriptInterpreter *script_interpreter = 169 target_sp->GetDebugger().GetScriptInterpreter(); 170 171 if (!script_interpreter) { 172 retval.assign("error: no ScriptInterpreter"); 173 return false; 174 } 175 176 return script_interpreter->GetScriptedSummary( 177 m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, options, 178 retval); 179 } 180 181 std::string ScriptSummaryFormat::GetDescription() { 182 StreamString sstr; 183 sstr.Printf("%s%s%s%s%s%s%s\n ", Cascades() ? "" : " (not cascading)", 184 !DoesPrintChildren(nullptr) ? "" : " (show children)", 185 !DoesPrintValue(nullptr) ? " (hide value)" : "", 186 IsOneLiner() ? " (one-line printout)" : "", 187 SkipsPointers() ? " (skip pointers)" : "", 188 SkipsReferences() ? " (skip references)" : "", 189 HideNames(nullptr) ? " (hide member names)" : ""); 190 if (m_python_script.empty()) { 191 if (m_function_name.empty()) { 192 sstr.PutCString("no backing script"); 193 } else { 194 sstr.PutCString(m_function_name); 195 } 196 } else { 197 sstr.PutCString(m_python_script); 198 } 199 return std::string(sstr.GetString()); 200 } 201