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 // We've already checked the case of a NULL valobj above. Let's put in an 84 // assert here to make sure someone doesn't take that out: 85 assert(valobj && "Must have a valid ValueObject to summarize"); 86 ValueObjectPrinter printer(*valobj, &s, DumpValueObjectOptions()); 87 printer.PrintChildrenOneLiner(HideNames(valobj)); 88 retval = std::string(s.GetString()); 89 return true; 90 } else { 91 if (FormatEntity::Format(m_format, s, &sc, &exe_ctx, 92 &sc.line_entry.range.GetBaseAddress(), valobj, 93 false, false)) { 94 retval.assign(std::string(s.GetString())); 95 return true; 96 } else { 97 retval.assign("error: summary string parsing error"); 98 return false; 99 } 100 } 101 } 102 103 std::string StringSummaryFormat::GetDescription() { 104 StreamString sstr; 105 106 sstr.Printf("`%s`%s%s%s%s%s%s%s%s%s", m_format_str.c_str(), 107 m_error.Fail() ? " error: " : "", 108 m_error.Fail() ? m_error.AsCString() : "", 109 Cascades() ? "" : " (not cascading)", 110 !DoesPrintChildren(nullptr) ? "" : " (show children)", 111 !DoesPrintValue(nullptr) ? " (hide value)" : "", 112 IsOneLiner() ? " (one-line printout)" : "", 113 SkipsPointers() ? " (skip pointers)" : "", 114 SkipsReferences() ? " (skip references)" : "", 115 HideNames(nullptr) ? " (hide member names)" : ""); 116 return std::string(sstr.GetString()); 117 } 118 119 CXXFunctionSummaryFormat::CXXFunctionSummaryFormat( 120 const TypeSummaryImpl::Flags &flags, Callback impl, const char *description) 121 : TypeSummaryImpl(Kind::eCallback, flags), m_impl(impl), 122 m_description(description ? description : "") {} 123 124 bool CXXFunctionSummaryFormat::FormatObject(ValueObject *valobj, 125 std::string &dest, 126 const TypeSummaryOptions &options) { 127 dest.clear(); 128 StreamString stream; 129 if (!m_impl || !m_impl(*valobj, stream, options)) 130 return false; 131 dest = std::string(stream.GetString()); 132 return true; 133 } 134 135 std::string CXXFunctionSummaryFormat::GetDescription() { 136 StreamString sstr; 137 sstr.Printf("%s%s%s%s%s%s%s %s", Cascades() ? "" : " (not cascading)", 138 !DoesPrintChildren(nullptr) ? "" : " (show children)", 139 !DoesPrintValue(nullptr) ? " (hide value)" : "", 140 IsOneLiner() ? " (one-line printout)" : "", 141 SkipsPointers() ? " (skip pointers)" : "", 142 SkipsReferences() ? " (skip references)" : "", 143 HideNames(nullptr) ? " (hide member names)" : "", 144 m_description.c_str()); 145 return std::string(sstr.GetString()); 146 } 147 148 ScriptSummaryFormat::ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags, 149 const char *function_name, 150 const char *python_script) 151 : TypeSummaryImpl(Kind::eScript, flags), m_function_name(), 152 m_python_script(), m_script_function_sp() { 153 if (function_name) 154 m_function_name.assign(function_name); 155 if (python_script) 156 m_python_script.assign(python_script); 157 } 158 159 bool ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval, 160 const TypeSummaryOptions &options) { 161 if (!valobj) 162 return false; 163 164 TargetSP target_sp(valobj->GetTargetSP()); 165 166 if (!target_sp) { 167 retval.assign("error: no target"); 168 return false; 169 } 170 171 ScriptInterpreter *script_interpreter = 172 target_sp->GetDebugger().GetScriptInterpreter(); 173 174 if (!script_interpreter) { 175 retval.assign("error: no ScriptInterpreter"); 176 return false; 177 } 178 179 return script_interpreter->GetScriptedSummary( 180 m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, options, 181 retval); 182 } 183 184 std::string ScriptSummaryFormat::GetDescription() { 185 StreamString sstr; 186 sstr.Printf("%s%s%s%s%s%s%s\n ", Cascades() ? "" : " (not cascading)", 187 !DoesPrintChildren(nullptr) ? "" : " (show children)", 188 !DoesPrintValue(nullptr) ? " (hide value)" : "", 189 IsOneLiner() ? " (one-line printout)" : "", 190 SkipsPointers() ? " (skip pointers)" : "", 191 SkipsReferences() ? " (skip references)" : "", 192 HideNames(nullptr) ? " (hide member names)" : ""); 193 if (m_python_script.empty()) { 194 if (m_function_name.empty()) { 195 sstr.PutCString("no backing script"); 196 } else { 197 sstr.PutCString(m_function_name); 198 } 199 } else { 200 sstr.PutCString(m_python_script); 201 } 202 return std::string(sstr.GetString()); 203 } 204