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