LLDB mainline
TypeSummary.cpp
Go to the documentation of this file.
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
10
14#include "lldb/lldb-public.h"
15
16#include "lldb/Core/Debugger.h"
23#include "lldb/Target/Target.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
31
33
37
42
48
50 uint32_t ptr_match_depth)
51 : m_flags(flags), m_kind(kind), m_ptr_match_depth(ptr_match_depth) {}
52
54 switch (m_kind) {
56 return "string";
57 case Kind::eCallback:
58 return "callback";
59 case Kind::eScript:
60 return "python";
61 case Kind::eInternal:
62 return "c++";
63 case Kind::eBytecode:
64 return "bytecode";
66 return "python class";
67 }
68 llvm_unreachable("Unknown type kind name");
69}
70
72 const char *format_cstr,
73 uint32_t ptr_match_depth)
74 : TypeSummaryImpl(Kind::eSummaryString, flags, ptr_match_depth),
75 m_format_str() {
76 SetSummaryString(format_cstr);
77}
78
79void StringSummaryFormat::SetSummaryString(const char *format_cstr) {
80 m_format.Clear();
81 if (format_cstr && format_cstr[0]) {
82 m_format_str = format_cstr;
83 m_error = FormatEntity::Parse(format_cstr, m_format);
84 } else {
85 m_format_str.clear();
86 m_error.Clear();
87 }
88}
89
90bool StringSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
91 const TypeSummaryOptions &options) {
92 if (!valobj) {
93 retval.assign("NULL ValueObject");
94 return false;
95 }
96
100 StackFrame *frame = exe_ctx.GetFramePtr();
101 if (frame)
102 sc = frame->GetSymbolContext(lldb::eSymbolContextEverything);
103
104 if (IsOneLiner()) {
105 // We've already checked the case of a NULL valobj above. Let's put in an
106 // assert here to make sure someone doesn't take that out:
107 assert(valobj && "Must have a valid ValueObject to summarize");
108 ValueObjectPrinter printer(*valobj, &s, DumpValueObjectOptions());
109 printer.PrintChildrenOneLiner(HideNames(valobj));
110 retval = std::string(s.GetString());
111 return true;
112 } else {
114 &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), false, false)
115 .Format(m_format, s, valobj)) {
116 retval.assign(std::string(s.GetString()));
117 return true;
118 } else {
119 retval.assign("error: summary string parsing error");
120 return false;
121 }
122 }
123}
124
126 StreamString sstr;
127
128 sstr.Printf("`%s`%s%s%s%s%s%s%s%s%s ptr-match-depth=%u", m_format_str.c_str(),
129 m_error.Fail() ? " error: " : "",
130 m_error.Fail() ? m_error.AsCString() : "",
131 Cascades() ? "" : " (not cascading)",
132 !DoesPrintChildren(nullptr) ? "" : " (show children)",
133 !DoesPrintValue(nullptr) ? " (hide value)" : "",
134 IsOneLiner() ? " (one-line printout)" : "",
135 SkipsPointers() ? " (skip pointers)" : "",
136 SkipsReferences() ? " (skip references)" : "",
137 HideNames(nullptr) ? " (hide member names)" : "",
139 return std::string(sstr.GetString());
140}
141
143
145 const TypeSummaryImpl::Flags &flags, Callback impl, const char *description,
146 uint32_t ptr_match_depth)
147 : TypeSummaryImpl(Kind::eCallback, flags, ptr_match_depth), m_impl(impl),
148 m_description(description ? description : "") {}
149
151 std::string &dest,
152 const TypeSummaryOptions &options) {
153 dest.clear();
154 StreamString stream;
155 if (!m_impl || !m_impl(*valobj, stream, options))
156 return false;
157 dest = std::string(stream.GetString());
158 return true;
159}
160
162 StreamString sstr;
163 sstr.Printf("%s%s%s%s%s%s%s ptr-match-depth=%u %s",
164 Cascades() ? "" : " (not cascading)",
165 !DoesPrintChildren(nullptr) ? "" : " (show children)",
166 !DoesPrintValue(nullptr) ? " (hide value)" : "",
167 IsOneLiner() ? " (one-line printout)" : "",
168 SkipsPointers() ? " (skip pointers)" : "",
169 SkipsReferences() ? " (skip references)" : "",
170 HideNames(nullptr) ? " (hide member names)" : "",
172 return std::string(sstr.GetString());
173}
174
176
178 const char *function_name,
179 const char *python_script,
180 uint32_t ptr_match_depth)
181 : TypeSummaryImpl(Kind::eScript, flags, ptr_match_depth), m_function_name(),
183 // Take preference in the python script name over the function name.
184 if (function_name) {
185 m_function_name.assign(function_name);
186 m_script_formatter_name = function_name;
187 }
188 if (python_script) {
189 m_python_script.assign(python_script);
190 m_script_formatter_name = python_script;
191 }
192
193 // Python scripts include the tabbing of the function def so we remove the
194 // leading spaces.
196 0, m_script_formatter_name.find_first_not_of(' '));
197}
198
199bool ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
200 const TypeSummaryOptions &options) {
201 if (!valobj)
202 return false;
203
204 TargetSP target_sp(valobj->GetTargetSP());
205
206 if (!target_sp) {
207 retval.assign("error: no target");
208 return false;
209 }
210
211 ScriptInterpreter *script_interpreter =
212 target_sp->GetDebugger().GetScriptInterpreter();
213
214 if (!script_interpreter) {
215 retval.assign("error: no ScriptInterpreter");
216 return false;
217 }
218
219 return script_interpreter->GetScriptedSummary(
220 m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, options,
221 retval);
222}
223
225 StreamString sstr;
226 sstr.Printf("%s%s%s%s%s%s%s ptr-match-depth=%u\n ",
227 Cascades() ? "" : " (not cascading)",
228 !DoesPrintChildren(nullptr) ? "" : " (show children)",
229 !DoesPrintValue(nullptr) ? " (hide value)" : "",
230 IsOneLiner() ? " (one-line printout)" : "",
231 SkipsPointers() ? " (skip pointers)" : "",
232 SkipsReferences() ? " (skip references)" : "",
233 HideNames(nullptr) ? " (hide member names)" : "",
235 if (m_python_script.empty()) {
236 if (m_function_name.empty()) {
237 sstr.PutCString("no backing script");
238 } else {
240 }
241 } else {
243 }
244 return std::string(sstr.GetString());
245}
246
248
250 const TypeSummaryImpl::Flags &flags, const char *class_name,
251 uint32_t ptr_match_depth)
252 : TypeSummaryImpl(Kind::eScriptedClass, flags, ptr_match_depth),
253 m_class_name(class_name ? class_name : ""), m_interface_sp() {}
254
256 std::string &retval,
257 const TypeSummaryOptions &options) {
258 if (!valobj)
259 return false;
260
261 TargetSP target_sp(valobj->GetTargetSP());
262
263 if (!target_sp) {
264 retval.assign("error: no target");
265 return false;
266 }
267
268 ScriptInterpreter *script_interpreter =
269 target_sp->GetDebugger().GetScriptInterpreter();
270
271 if (!script_interpreter) {
272 retval.assign("error: no ScriptInterpreter");
273 return false;
274 }
275
276 if (!m_interface_sp) {
278 if (!m_interface_sp) {
279 retval.assign("error: no ScriptedStringSummaryInterface");
280 return false;
281 }
282
283 llvm::Expected<StructuredData::GenericSP> obj_or_err =
284 m_interface_sp->CreatePluginObject(m_class_name);
285 if (!obj_or_err) {
286 retval.assign(llvm::toString(obj_or_err.takeError()));
287 m_interface_sp.reset();
288 return false;
289 }
290 }
291
292 llvm::Expected<std::string> summary =
293 m_interface_sp->GetSummary(*valobj, options);
294 if (!summary) {
295 retval.assign(llvm::toString(summary.takeError()));
296 return false;
297 }
298
299 retval = std::move(*summary);
300 return true;
301}
302
304 StreamString sstr;
305 sstr.Printf("%s%s%s%s%s%s%s ptr-match-depth=%u\n ",
306 Cascades() ? "" : " (not cascading)",
307 !DoesPrintChildren(nullptr) ? "" : " (show children)",
308 !DoesPrintValue(nullptr) ? " (hide value)" : "",
309 IsOneLiner() ? " (one-line printout)" : "",
310 SkipsPointers() ? " (skip pointers)" : "",
311 SkipsReferences() ? " (skip references)" : "",
312 HideNames(nullptr) ? " (hide member names)" : "",
315 return std::string(sstr.GetString());
316}
317
319
321 const TypeSummaryImpl::Flags &flags,
322 std::unique_ptr<llvm::MemoryBuffer> bytecode)
323 : TypeSummaryImpl(Kind::eBytecode, flags), m_bytecode(std::move(bytecode)) {
324}
325
327 std::string &retval,
328 const TypeSummaryOptions &options) {
329 if (!valobj)
330 return false;
331
332 TargetSP target_sp(valobj->GetTargetSP());
333
334 if (!target_sp) {
335 retval.assign("error: no target");
336 return false;
337 }
338
339 FormatterBytecode::ControlStack control({m_bytecode->getBuffer()});
340 FormatterBytecode::DataStack data({valobj->GetSP()});
342 control, data, FormatterBytecode::sig_summary);
343 if (error) {
344 retval = llvm::toString(std::move(error));
345 return false;
346 }
347 if (!data.size()) {
348 retval = "empty stack";
349 return false;
350 }
351 auto &top = data.back();
352 retval = "";
353 llvm::raw_string_ostream os(retval);
354 if (auto s = std::get_if<std::string>(&top))
355 os << *s;
356 else if (auto u = std::get_if<uint64_t>(&top))
357 os << *u;
358 else if (auto i = std::get_if<int64_t>(&top))
359 os << *i;
360 else if (auto valobj = std::get_if<ValueObjectSP>(&top)) {
361 if (!valobj->get())
362 os << "empty object";
363 else
364 os << valobj->get()->GetValueAsCString();
365 } else if (auto type = std::get_if<CompilerType>(&top)) {
366 os << type->TypeDescription();
367 } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&top)) {
368 os << toString(*sel);
369 }
370 return true;
371}
372
374 StreamString sstr;
375 sstr.Printf("%s%s%s%s%s%s%s\n ", Cascades() ? "" : " (not cascading)",
376 !DoesPrintChildren(nullptr) ? "" : " (show children)",
377 !DoesPrintValue(nullptr) ? " (hide value)" : "",
378 IsOneLiner() ? " (one-line printout)" : "",
379 SkipsPointers() ? " (skip pointers)" : "",
380 SkipsReferences() ? " (skip references)" : "",
381 HideNames(nullptr) ? " (hide member names)" : "");
382 // FIXME: sstr.PutCString(disassembly);
383 return std::string(sstr.GetString());
384}
385
387 return "LLDB bytecode formatter";
388}
static llvm::raw_ostream & error(Stream &strm)
Address & GetBaseAddress()
Get accessor for the base address of the range.
std::string GetDescription() override
BytecodeSummaryFormat(const TypeSummaryImpl::Flags &flags, std::unique_ptr< llvm::MemoryBuffer > bytecode)
std::unique_ptr< llvm::MemoryBuffer > m_bytecode
std::string GetName() override
Get the name of the Type Summary Provider, either a C++ class, a summary string, or a script function...
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
bool Format(const Entry &entry, Stream &s, ValueObject *valobj=nullptr)
virtual lldb::ScriptedStringSummaryInterfaceSP CreateScriptedStringSummaryInterface()
virtual bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval)
This base class provides an interface to stack frames.
Definition StackFrame.h:44
virtual const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
Defines a symbol context baton that can be handed other debug core functions.
LineEntry line_entry
The LineEntry for a given query.
virtual bool HideNames(ValueObject *valobj) const
virtual std::string GetSummaryKindName()
Get the name of the kind of Summary Provider, either c++, summary string, script or python.
TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags, uint32_t ptr_match_depth=1)
virtual bool DoesPrintValue(ValueObject *valobj) const
virtual bool DoesPrintChildren(ValueObject *valobj) const
lldb::TypeSummaryCapping m_capping
Definition TypeSummary.h:46
lldb::LanguageType GetLanguage() const
TypeSummaryOptions & SetCapping(lldb::TypeSummaryCapping)
TypeSummaryOptions & SetLanguage(lldb::LanguageType)
lldb::TypeSummaryCapping GetCapping() const
bool PrintChildrenOneLiner(bool hide_names)
lldb::ValueObjectSP GetSP()
lldb::TargetSP GetTargetSP() const
virtual const char * GetValueAsCString()
const ExecutionContextRef & GetExecutionContextRef() const
Status Parse(const llvm::StringRef &format, Entry &entry)
std::vector< ControlStackElement > ControlStack
llvm::Error Interpret(ControlStack &control, DataStack &data, Signatures sig)
A class that represents a running process on the host machine.
std::string toString(FormatterBytecode::OpCodes op)
TypeSummaryCapping
Whether a summary should cap how much data it returns to users or not.
LanguageType
Programming language type.
std::shared_ptr< lldb_private::Target > TargetSP
std::function< bool(ValueObject &, Stream &, const TypeSummaryOptions &)> Callback
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
CXXFunctionSummaryFormat(const TypeSummaryImpl::Flags &flags, Callback impl, const char *description, uint32_t ptr_match_depth=1)
std::string GetName() override
Get the name of the Type Summary Provider, either a C++ class, a summary string, or a script function...
AddressRange range
The section offset address range for this line entry.
Definition LineEntry.h:137
std::string GetDescription() override
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
StructuredData::ObjectSP m_script_function_sp
std::string GetName() override
Get the name of the Type Summary Provider, either a C++ class, a summary string, or a script function...
ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *function_name, const char *python_script=nullptr, uint32_t ptr_match_depth=1)
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
ScriptedSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *class_name, uint32_t ptr_match_depth=1)
lldb::ScriptedStringSummaryInterfaceSP m_interface_sp
std::string GetDescription() override
std::string GetName() override
Get the name of the Type Summary Provider, either a C++ class, a summary string, or a script function...
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
StringSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *f, uint32_t ptr_match_depth=1)
std::string GetName() override
Get the name of the Type Summary Provider, either a C++ class, a summary string, or a script function...
void SetSummaryString(const char *f)
std::string GetDescription() override