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
11#include "FormatterBytecode.h"
13#include "lldb/lldb-public.h"
14
15#include "lldb/Core/Debugger.h"
20#include "lldb/Target/Target.h"
23
24using namespace lldb;
25using namespace lldb_private;
26
28
30
34
39
45
47 uint32_t ptr_match_depth)
48 : m_flags(flags), m_kind(kind), m_ptr_match_depth(ptr_match_depth) {}
49
51 switch (m_kind) {
53 return "string";
54 case Kind::eCallback:
55 return "callback";
56 case Kind::eScript:
57 return "python";
58 case Kind::eInternal:
59 return "c++";
60 case Kind::eBytecode:
61 return "bytecode";
62 }
63 llvm_unreachable("Unknown type kind name");
64}
65
67 const char *format_cstr,
68 uint32_t ptr_match_depth)
69 : TypeSummaryImpl(Kind::eSummaryString, flags, ptr_match_depth),
70 m_format_str() {
71 SetSummaryString(format_cstr);
72}
73
74void StringSummaryFormat::SetSummaryString(const char *format_cstr) {
75 m_format.Clear();
76 if (format_cstr && format_cstr[0]) {
77 m_format_str = format_cstr;
78 m_error = FormatEntity::Parse(format_cstr, m_format);
79 } else {
80 m_format_str.clear();
81 m_error.Clear();
82 }
83}
84
85bool StringSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
86 const TypeSummaryOptions &options) {
87 if (!valobj) {
88 retval.assign("NULL ValueObject");
89 return false;
90 }
91
95 StackFrame *frame = exe_ctx.GetFramePtr();
96 if (frame)
97 sc = frame->GetSymbolContext(lldb::eSymbolContextEverything);
98
99 if (IsOneLiner()) {
100 // We've already checked the case of a NULL valobj above. Let's put in an
101 // assert here to make sure someone doesn't take that out:
102 assert(valobj && "Must have a valid ValueObject to summarize");
103 ValueObjectPrinter printer(*valobj, &s, DumpValueObjectOptions());
104 printer.PrintChildrenOneLiner(HideNames(valobj));
105 retval = std::string(s.GetString());
106 return true;
107 } else {
108 if (FormatEntity::Format(m_format, s, &sc, &exe_ctx,
109 &sc.line_entry.range.GetBaseAddress(), valobj,
110 false, false)) {
111 retval.assign(std::string(s.GetString()));
112 return true;
113 } else {
114 retval.assign("error: summary string parsing error");
115 return false;
116 }
117 }
118}
119
121 StreamString sstr;
122
123 sstr.Printf("`%s`%s%s%s%s%s%s%s%s%s ptr-match-depth=%u", m_format_str.c_str(),
124 m_error.Fail() ? " error: " : "",
125 m_error.Fail() ? m_error.AsCString() : "",
126 Cascades() ? "" : " (not cascading)",
127 !DoesPrintChildren(nullptr) ? "" : " (show children)",
128 !DoesPrintValue(nullptr) ? " (hide value)" : "",
129 IsOneLiner() ? " (one-line printout)" : "",
130 SkipsPointers() ? " (skip pointers)" : "",
131 SkipsReferences() ? " (skip references)" : "",
132 HideNames(nullptr) ? " (hide member names)" : "",
134 return std::string(sstr.GetString());
135}
136
138
140 const TypeSummaryImpl::Flags &flags, Callback impl, const char *description,
141 uint32_t ptr_match_depth)
142 : TypeSummaryImpl(Kind::eCallback, flags, ptr_match_depth), m_impl(impl),
143 m_description(description ? description : "") {}
144
146 std::string &dest,
147 const TypeSummaryOptions &options) {
148 dest.clear();
149 StreamString stream;
150 if (!m_impl || !m_impl(*valobj, stream, options))
151 return false;
152 dest = std::string(stream.GetString());
153 return true;
154}
155
157 StreamString sstr;
158 sstr.Printf("%s%s%s%s%s%s%s ptr-match-depth=%u %s",
159 Cascades() ? "" : " (not cascading)",
160 !DoesPrintChildren(nullptr) ? "" : " (show children)",
161 !DoesPrintValue(nullptr) ? " (hide value)" : "",
162 IsOneLiner() ? " (one-line printout)" : "",
163 SkipsPointers() ? " (skip pointers)" : "",
164 SkipsReferences() ? " (skip references)" : "",
165 HideNames(nullptr) ? " (hide member names)" : "",
167 return std::string(sstr.GetString());
168}
169
171
173 const char *function_name,
174 const char *python_script,
175 uint32_t ptr_match_depth)
176 : TypeSummaryImpl(Kind::eScript, flags, ptr_match_depth), m_function_name(),
178 // Take preference in the python script name over the function name.
179 if (function_name) {
180 m_function_name.assign(function_name);
181 m_script_formatter_name = function_name;
182 }
183 if (python_script) {
184 m_python_script.assign(python_script);
185 m_script_formatter_name = python_script;
186 }
187
188 // Python scripts include the tabbing of the function def so we remove the
189 // leading spaces.
191 0, m_script_formatter_name.find_first_not_of(' '));
192}
193
194bool ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
195 const TypeSummaryOptions &options) {
196 if (!valobj)
197 return false;
198
199 TargetSP target_sp(valobj->GetTargetSP());
200
201 if (!target_sp) {
202 retval.assign("error: no target");
203 return false;
204 }
205
206 ScriptInterpreter *script_interpreter =
207 target_sp->GetDebugger().GetScriptInterpreter();
208
209 if (!script_interpreter) {
210 retval.assign("error: no ScriptInterpreter");
211 return false;
212 }
213
214 return script_interpreter->GetScriptedSummary(
215 m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, options,
216 retval);
217}
218
220 StreamString sstr;
221 sstr.Printf("%s%s%s%s%s%s%s ptr-match-depth=%u\n ",
222 Cascades() ? "" : " (not cascading)",
223 !DoesPrintChildren(nullptr) ? "" : " (show children)",
224 !DoesPrintValue(nullptr) ? " (hide value)" : "",
225 IsOneLiner() ? " (one-line printout)" : "",
226 SkipsPointers() ? " (skip pointers)" : "",
227 SkipsReferences() ? " (skip references)" : "",
228 HideNames(nullptr) ? " (hide member names)" : "",
230 if (m_python_script.empty()) {
231 if (m_function_name.empty()) {
232 sstr.PutCString("no backing script");
233 } else {
235 }
236 } else {
238 }
239 return std::string(sstr.GetString());
240}
241
243
245 const TypeSummaryImpl::Flags &flags,
246 std::unique_ptr<llvm::MemoryBuffer> bytecode)
247 : TypeSummaryImpl(Kind::eBytecode, flags), m_bytecode(std::move(bytecode)) {
248}
249
251 std::string &retval,
252 const TypeSummaryOptions &options) {
253 if (!valobj)
254 return false;
255
256 TargetSP target_sp(valobj->GetTargetSP());
257
258 if (!target_sp) {
259 retval.assign("error: no target");
260 return false;
261 }
262
263 std::vector<FormatterBytecode::ControlStackElement> control(
264 {m_bytecode->getBuffer()});
265 FormatterBytecode::DataStack data({valobj->GetSP()});
267 control, data, FormatterBytecode::sel_summary);
268 if (error) {
269 retval = llvm::toString(std::move(error));
270 return false;
271 }
272 if (!data.size()) {
273 retval = "empty stack";
274 return false;
275 }
276 auto &top = data.back();
277 retval = "";
278 llvm::raw_string_ostream os(retval);
279 if (auto s = std::get_if<std::string>(&top))
280 os << *s;
281 else if (auto u = std::get_if<uint64_t>(&top))
282 os << *u;
283 else if (auto i = std::get_if<int64_t>(&top))
284 os << *i;
285 else if (auto valobj = std::get_if<ValueObjectSP>(&top)) {
286 if (!valobj->get())
287 os << "empty object";
288 else
289 os << valobj->get()->GetValueAsCString();
290 } else if (auto type = std::get_if<CompilerType>(&top)) {
291 os << type->TypeDescription();
292 } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&top)) {
293 os << toString(*sel);
294 }
295 return true;
296}
297
299 StreamString sstr;
300 sstr.Printf("%s%s%s%s%s%s%s\n ", Cascades() ? "" : " (not cascading)",
301 !DoesPrintChildren(nullptr) ? "" : " (show children)",
302 !DoesPrintValue(nullptr) ? " (hide value)" : "",
303 IsOneLiner() ? " (one-line printout)" : "",
304 SkipsPointers() ? " (skip pointers)" : "",
305 SkipsReferences() ? " (skip references)" : "",
306 HideNames(nullptr) ? " (hide member names)" : "");
307 // FIXME: sstr.PutCString(disassembly);
308 return std::string(sstr.GetString());
309}
310
312 return "LLDB bytecode formatter";
313}
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.
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
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:65
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)
bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address *addr, ValueObject *valobj, bool function_changed, bool initial_function)
llvm::Error Interpret(std::vector< ControlStackElement > &control, DataStack &data, Selectors sel)
A class that represents a running process on the host machine.
const char * toString(AppleArm64ExceptionClass EC)
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
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