xref: /llvm-project/lldb/source/DataFormatters/FormatterSection.cpp (revision f22cff7675f7f64aa52204f4426f5047cc75fbb9)
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 
9 #include "FormatterBytecode.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/DataFormatters/DataVisualization.h"
12 #include "lldb/Utility/LLDBLog.h"
13 
14 using namespace lldb;
15 
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();
21   if (!sections)
22     return;
23 
24   auto section_sp = sections->FindSectionByType(section_type, true);
25   if (!section_sp)
26     return;
27 
28   TypeCategoryImplSP category;
29   DataVisualization::Categories::GetCategory(ConstString("default"), category);
30 
31   // The type summary record is serialized as follows.
32   //
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
39   //   * The entry
40   //
41   // Integers are encoded using ULEB.
42   //
43   // Strings are encoded with first a length (ULEB), then the string contents,
44   // and lastly a null terminator. The length includes the null.
45 
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)
56         continue;
57       cursor.seek(cursor.tell() - 1);
58       break;
59     }
60     uint64_t version = section.getULEB128(cursor);
61     uint64_t record_size = section.getULEB128(cursor);
62     if (version == 1) {
63       llvm::DataExtractor record(section.getData().drop_front(cursor.tell()),
64                                  le, addr_size);
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();
69       if (!error)
70         fn(llvm::DataExtractor(record.getData().drop_front(cursor.tell()), le,
71                                addr_size),
72            type_name);
73       else
74         LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(error),
75                        "{0}");
76     } else {
77       // Skip unsupported record.
78       LLDB_LOG(
79           GetLog(LLDBLog::DataFormatters),
80           "Skipping unsupported embedded type summary of version {0} in {1}.",
81           version, module.GetFileSpec());
82     }
83     section.skip(cursor, record_size);
84   }
85   if (!cursor)
86     LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), "{0}");
87 }
88 
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"),
95                                                    category);
96         // The type summary record is serialized as follows.
97         //
98         //   * The size of the summary string
99         //   * The summary string
100         //
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);
106         if (!cursor) {
107           LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),
108                          "{0}");
109           return;
110         }
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);
116           return;
117         }
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());
128       });
129 }
130 
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"),
140                                                    category);
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);
147           if (!cursor) {
148             LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),
149                            "{0}");
150             return;
151           }
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());
163           } else
164             LLDB_LOG(GetLog(LLDBLog::DataFormatters),
165                      "Unsupported formatter signature {0} for '{1}' in {2}",
166                      signature, type_name, module_sp->GetFileSpec());
167         }
168       });
169 }
170 } // namespace lldb_private
171