1 //===-- FormatterBytecode.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "FormatterBytecode.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/DataFormatters/DataVisualization.h"
12 #include "lldb/Utility/LLDBLog.h"
16 namespace lldb_private
{
17 static void ForEachFormatterInModule(
18 Module
&module
, SectionType section_type
,
19 std::function
<void(llvm::DataExtractor
, llvm::StringRef
)> fn
) {
20 auto *sections
= module
.GetSectionList();
24 auto section_sp
= sections
->FindSectionByType(section_type
, true);
28 TypeCategoryImplSP category
;
29 DataVisualization::Categories::GetCategory(ConstString("default"), category
);
31 // The type summary record is serialized as follows.
33 // Each record contains, in order:
34 // * Version number of the record format
35 // * The remaining size of the record
36 // * The size of the type identifier
37 // * The type identifier, either a type name, or a regex
38 // * The size of the entry
41 // Integers are encoded using ULEB.
43 // Strings are encoded with first a length (ULEB), then the string contents,
44 // and lastly a null terminator. The length includes the null.
46 DataExtractor lldb_extractor
;
47 auto section_size
= section_sp
->GetSectionData(lldb_extractor
);
48 llvm::DataExtractor section
= lldb_extractor
.GetAsLLVM();
49 bool le
= section
.isLittleEndian();
50 uint8_t addr_size
= section
.getAddressSize();
51 llvm::DataExtractor::Cursor
cursor(0);
52 while (cursor
&& cursor
.tell() < section_size
) {
53 while (cursor
&& cursor
.tell() < section_size
) {
54 // Skip over 0 padding.
55 if (section
.getU8(cursor
) == 0)
57 cursor
.seek(cursor
.tell() - 1);
60 uint64_t version
= section
.getULEB128(cursor
);
61 uint64_t record_size
= section
.getULEB128(cursor
);
63 llvm::DataExtractor
record(section
.getData().drop_front(cursor
.tell()),
65 llvm::DataExtractor::Cursor
cursor(0);
66 uint64_t type_size
= record
.getULEB128(cursor
);
67 llvm::StringRef type_name
= record
.getBytes(cursor
, type_size
);
68 llvm::Error error
= cursor
.takeError();
70 fn(llvm::DataExtractor(record
.getData().drop_front(cursor
.tell()), le
,
74 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters
), std::move(error
),
77 // Skip unsupported record.
79 GetLog(LLDBLog::DataFormatters
),
80 "Skipping unsupported embedded type summary of version {0} in {1}.",
81 version
, module
.GetFileSpec());
83 section
.skip(cursor
, record_size
);
86 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters
), cursor
.takeError(), "{0}");
89 void LoadTypeSummariesForModule(ModuleSP module_sp
) {
90 ForEachFormatterInModule(
91 *module_sp
, eSectionTypeLLDBTypeSummaries
,
92 [&](llvm::DataExtractor extractor
, llvm::StringRef type_name
) {
93 TypeCategoryImplSP category
;
94 DataVisualization::Categories::GetCategory(ConstString("default"),
96 // The type summary record is serialized as follows.
98 // * The size of the summary string
99 // * The summary string
101 // Integers are encoded using ULEB.
102 llvm::DataExtractor::Cursor
cursor(0);
103 uint64_t summary_size
= extractor
.getULEB128(cursor
);
104 llvm::StringRef summary_string
=
105 extractor
.getBytes(cursor
, summary_size
);
107 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters
), cursor
.takeError(),
111 if (type_name
.empty() || summary_string
.empty()) {
112 LLDB_LOG(GetLog(LLDBLog::DataFormatters
),
113 "Missing string(s) in embedded type summary in {0}, "
114 "type_name={1}, summary={2}",
115 module_sp
->GetFileSpec(), type_name
, summary_string
);
118 TypeSummaryImpl::Flags flags
;
119 auto summary_sp
= std::make_shared
<StringSummaryFormat
>(
120 flags
, summary_string
.str().c_str());
121 FormatterMatchType match_type
= eFormatterMatchExact
;
122 if (type_name
.front() == '^')
123 match_type
= eFormatterMatchRegex
;
124 category
->AddTypeSummary(type_name
, match_type
, summary_sp
);
125 LLDB_LOG(GetLog(LLDBLog::DataFormatters
),
126 "Loaded embedded type summary for '{0}' from {1}.", type_name
,
127 module_sp
->GetFileSpec());
131 void LoadFormattersForModule(ModuleSP module_sp
) {
132 ForEachFormatterInModule(
133 *module_sp
, eSectionTypeLLDBFormatters
,
134 [&](llvm::DataExtractor extractor
, llvm::StringRef type_name
) {
135 // * Function signature (1 byte)
136 // * Length of the program (ULEB128)
137 // * The program bytecode
138 TypeCategoryImplSP category
;
139 DataVisualization::Categories::GetCategory(ConstString("default"),
141 llvm::DataExtractor::Cursor
cursor(0);
142 uint64_t flags
= extractor
.getULEB128(cursor
);
143 while (cursor
&& cursor
.tell() < extractor
.size()) {
144 uint8_t signature
= extractor
.getU8(cursor
);
145 uint64_t size
= extractor
.getULEB128(cursor
);
146 llvm::StringRef bytecode
= extractor
.getBytes(cursor
, size
);
148 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters
), cursor
.takeError(),
152 if (signature
== 0) {
153 auto summary_sp
= std::make_shared
<BytecodeSummaryFormat
>(
154 TypeSummaryImpl::Flags(flags
),
155 llvm::MemoryBuffer::getMemBufferCopy(bytecode
));
156 FormatterMatchType match_type
= eFormatterMatchExact
;
157 if (type_name
.front() == '^')
158 match_type
= eFormatterMatchRegex
;
159 category
->AddTypeSummary(type_name
, match_type
, summary_sp
);
160 LLDB_LOG(GetLog(LLDBLog::DataFormatters
),
161 "Loaded embedded type summary for '{0}' from {1}.",
162 type_name
, module_sp
->GetFileSpec());
164 LLDB_LOG(GetLog(LLDBLog::DataFormatters
),
165 "Unsupported formatter signature {0} for '{1}' in {2}",
166 signature
, type_name
, module_sp
->GetFileSpec());
170 } // namespace lldb_private