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