LLDB mainline
FormatterSection.cpp
Go to the documentation of this file.
1//===-- FormatterBytecode.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 "lldb/Core/Module.h"
16#include "llvm/Support/MemoryBuffer.h"
17#include <memory>
18
19using namespace lldb;
20
21namespace lldb_private {
22
23static bool skipPadding(llvm::DataExtractor &section,
24 llvm::DataExtractor::Cursor &cursor) {
25 while (!section.eof(cursor)) {
26 if (section.getU8(cursor) == 0)
27 continue;
28
29 cursor.seek(cursor.tell() - 1);
30 return true;
31 }
32
33 return false; // reached EOF
34}
35
37 Module &module, SectionType section_type,
38 std::function<void(llvm::DataExtractor, llvm::StringRef, uint32_t)> fn) {
39 auto *sections = module.GetSectionList();
40 if (!sections)
41 return;
42
43 auto section_sp = sections->FindSectionByType(section_type, true);
44 if (!section_sp)
45 return;
46
47 TypeCategoryImplSP category;
49
50 // The type summary record is serialized as follows.
51 //
52 // Each record contains, in order:
53 // * Version number of the record format
54 // * The remaining size of the record
55 // * The size of the type identifier
56 // * The type identifier, either a type name, or a regex
57 // * The size of the entry
58 // * The entry
59 //
60 // The version also determines the calling convention of the entry's
61 // bytecode methods (see BytecodeSyntheticChildren).
62 //
63 // Integers are encoded using ULEB.
64 //
65 // Strings are encoded with first a length (ULEB), then the string contents,
66 // and lastly a null terminator. The length includes the null.
67
68 DataExtractor lldb_extractor;
69 auto section_size = section_sp->GetSectionData(lldb_extractor);
70 llvm::DataExtractor section = lldb_extractor.GetAsLLVM();
71 bool le = section.isLittleEndian();
72 llvm::DataExtractor::Cursor cursor(0);
73 while (cursor && cursor.tell() < section_size) {
74 if (!skipPadding(section, cursor))
75 break;
76
77 uint64_t version = section.getULEB128(cursor);
78 uint64_t record_size = section.getULEB128(cursor);
79 if (cursor && record_size > section_size - cursor.tell()) {
81 "Record size {0} exceeds the remaining size of the embedded "
82 "formatter section in {1}; ignoring the rest of the section.",
83 record_size, module.GetFileSpec());
84 break;
85 }
86 if (version == 1 || version == 2) {
87 llvm::DataExtractor record(
88 section.getData().drop_front(cursor.tell()).take_front(record_size),
89 le);
90 llvm::DataExtractor::Cursor cursor(0);
91 uint64_t type_size = record.getULEB128(cursor);
92 llvm::StringRef type_name = record.getBytes(cursor, type_size);
93 llvm::Error error = cursor.takeError();
94 if (!error)
95 fn(llvm::DataExtractor(record.getData().drop_front(cursor.tell()), le),
96 type_name, version);
97 else
99 "{0}");
100 } else {
101 // Skip unsupported record.
102 LLDB_LOG(
104 "Skipping unsupported embedded type summary of version {0} in {1}.",
105 version, module.GetFileSpec());
106 }
107 section.skip(cursor, record_size);
108 }
109 if (!cursor)
110 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), "{0}");
111}
112
116 [&](llvm::DataExtractor extractor, llvm::StringRef type_name,
117 uint32_t version) {
118 TypeCategoryImplSP category;
120 // The type summary record is serialized as follows.
121 //
122 // * The size of the summary string
123 // * The summary string
124 //
125 // Integers are encoded using ULEB.
126 llvm::DataExtractor::Cursor cursor(0);
127 uint64_t summary_size = extractor.getULEB128(cursor);
128 llvm::StringRef summary_string =
129 extractor.getBytes(cursor, summary_size);
130 if (!cursor) {
131 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),
132 "{0}");
133 return;
134 }
135 if (type_name.empty() || summary_string.empty()) {
137 "Missing string(s) in embedded type summary in {0}, "
138 "type_name={1}, summary={2}",
139 module_sp->GetFileSpec(), type_name, summary_string);
140 return;
141 }
143 auto summary_sp = std::make_shared<StringSummaryFormat>(
144 flags, summary_string.str().c_str());
146 if (type_name.front() == '^')
147 match_type = eFormatterMatchRegex;
148 category->AddTypeSummary(type_name, match_type, summary_sp);
150 "Loaded embedded type summary for '{0}' from {1}.", type_name,
151 module_sp->GetFileSpec());
152 });
153}
154
155static BytecodeSyntheticChildren::SyntheticBytecodeImplementation
157 llvm::MutableArrayRef<std::unique_ptr<llvm::MemoryBuffer>> methods,
158 uint32_t version) {
159 using Signatures = FormatterBytecode::Signatures;
161 impl.version = version;
162 impl.init = std::move(methods[Signatures::sig_init]);
163 impl.update = std::move(methods[Signatures::sig_update]);
164 impl.num_children = std::move(methods[Signatures::sig_get_num_children]);
165 impl.get_child_at_index =
166 std::move(methods[Signatures::sig_get_child_at_index]);
167 impl.get_child_index = std::move(methods[Signatures::sig_get_child_index]);
168 return impl;
169}
170
173 *module_sp, eSectionTypeLLDBFormatters,
174 [&](llvm::DataExtractor extractor, llvm::StringRef type_name,
175 uint32_t version) {
176 // * Flags (ULEB128)
177 // * Function signature (1 byte)
178 // * Length of the program (ULEB128)
179 // * The program bytecode
180 TypeCategoryImplSP category;
182 llvm::DataExtractor::Cursor cursor(0);
183 uint64_t flags = extractor.getULEB128(cursor);
184
185 std::unique_ptr<llvm::MemoryBuffer> summary_func_up;
186 std::array<std::unique_ptr<llvm::MemoryBuffer>, kSignatureCount>
187 synthetic_methods;
188 bool has_synthetic_method = false;
189 using Signatures = FormatterBytecode::Signatures;
190 while (cursor && cursor.tell() < extractor.size()) {
191 auto signature = static_cast<Signatures>(extractor.getU8(cursor));
192 uint64_t size = extractor.getULEB128(cursor);
193 llvm::StringRef bytecode = extractor.getBytes(cursor, size);
194 if (!cursor)
195 break;
196 auto buffer_up = llvm::MemoryBuffer::getMemBufferCopy(bytecode);
197 if (signature == Signatures::sig_summary)
198 summary_func_up = std::move(buffer_up);
199 else if (signature <= Signatures::sig_update) {
200 synthetic_methods[signature] = std::move(buffer_up);
201 has_synthetic_method = true;
202 } else
204 "Unsupported formatter signature {0} for '{1}' in {2}",
205 signature, type_name, module_sp->GetFileSpec());
206 }
207 if (!cursor) {
208 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),
209 "{0}");
210 return;
211 }
212
214 if (type_name.front() == '^')
215 match_type = eFormatterMatchRegex;
216
217 if (summary_func_up) {
218 auto summary_sp = std::make_shared<BytecodeSummaryFormat>(
219 TypeSummaryImpl::Flags(flags), std::move(summary_func_up),
220 version);
221 category->AddTypeSummary(type_name, match_type, summary_sp);
223 "Loaded embedded type summary for '{0}' from {1}.",
224 type_name, module_sp->GetFileSpec());
225 } else if (has_synthetic_method) {
227 CreateSyntheticImpl(synthetic_methods, version);
228 auto synthetic_children_sp =
229 std::make_shared<BytecodeSyntheticChildren>(std::move(impl));
230 category->AddTypeSynthetic(type_name, match_type,
231 synthetic_children_sp);
233 "Loaded embedded type synthetic for '{0}' from {1}.",
234 type_name, module_sp->GetFileSpec());
235 } else {
237 "No summary or synthetic methods found for '{0}' in {1}, "
238 "not registering a formatter.",
239 type_name, module_sp->GetFileSpec());
240 }
241 });
242}
243} // namespace lldb_private
static llvm::raw_ostream & error(Stream &strm)
#define kSignatureCount
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:382
An data extractor class.
llvm::DataExtractor GetAsLLVM() const
static bool GetCategory(llvm::StringRef category, lldb::TypeCategoryImplSP &entry, bool allow_create=true)
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:92
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition Module.h:448
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
static bool skipPadding(llvm::DataExtractor &section, llvm::DataExtractor::Cursor &cursor)
void LoadTypeSummariesForModule(lldb::ModuleSP module_sp)
Load type summaries embedded in the binary.
static BytecodeSyntheticChildren::SyntheticBytecodeImplementation CreateSyntheticImpl(llvm::MutableArrayRef< std::unique_ptr< llvm::MemoryBuffer > > methods, uint32_t version)
static void ForEachFormatterInModule(Module &module, SectionType section_type, std::function< void(llvm::DataExtractor, llvm::StringRef, uint32_t)> fn)
void LoadFormattersForModule(lldb::ModuleSP module_sp)
Load data formatters embedded in the binary.
FormatterMatchType
Type of match to be performed when looking for a formatter for a data type.
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
@ eSectionTypeLLDBFormatters
@ eSectionTypeLLDBTypeSummaries
std::shared_ptr< lldb_private::Module > ModuleSP
uint32_t version
The version of this record. Specs are found in formatterbytecode.md.