xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- ManualDWARFIndex.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 "Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.h"
10 #include "lldb/Core/DataFileCache.h"
11 #include "lldb/Utility/DataEncoder.h"
12 #include "lldb/Utility/DataExtractor.h"
13 #include <cstdint>
14 
15 using namespace lldb_private;
16 using namespace lldb_private::plugin::dwarf;
17 
18 namespace {
19 // Define IDs for the different tables when encoding and decoding the
20 // ManualDWARFIndex NameToDIE objects so we can avoid saving any empty maps.
21 enum DataID {
22   kDataIDFunctionBasenames = 1u,
23   kDataIDFunctionFullnames,
24   kDataIDFunctionMethods,
25   kDataIDFunctionSelectors,
26   kDataIDFunctionObjcClassSelectors,
27   kDataIDGlobals,
28   kDataIDTypes,
29   kDataIDNamespaces,
30   kDataIDEnd = 255u,
31 };
32 } // namespace
33 
34 // Version 2 changes the encoding of DIERef objects used in the DWARF manual
35 // index name tables. See DIERef class for details.
36 static constexpr uint32_t CURRENT_CACHE_VERSION = 2;
37 
38 static constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX");
39 
40 std::optional<IndexSet<NameToDIE>>
DecodeIndexSet(const DataExtractor & data,lldb::offset_t * offset_ptr)41 plugin::dwarf::DecodeIndexSet(const DataExtractor &data,
42                               lldb::offset_t *offset_ptr) {
43   StringTableReader strtab;
44   // We now decode the string table for all strings in the data cache file.
45   if (!strtab.Decode(data, offset_ptr))
46     return std::nullopt;
47 
48   llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4);
49   if (identifier != kIdentifierManualDWARFIndex)
50     return std::nullopt;
51   const uint32_t version = data.GetU32(offset_ptr);
52   if (version != CURRENT_CACHE_VERSION)
53     return std::nullopt;
54 
55   IndexSet<NameToDIE> result;
56   while (true) {
57     switch (data.GetU8(offset_ptr)) {
58     default:
59       // If we got here, this is not expected, we expect the data IDs to match
60       // one of the values from the DataID enumeration.
61       return std::nullopt;
62     case kDataIDFunctionBasenames:
63       if (!result.function_basenames.Decode(data, offset_ptr, strtab))
64         return std::nullopt;
65       break;
66     case kDataIDFunctionFullnames:
67       if (!result.function_fullnames.Decode(data, offset_ptr, strtab))
68         return std::nullopt;
69       break;
70     case kDataIDFunctionMethods:
71       if (!result.function_methods.Decode(data, offset_ptr, strtab))
72         return std::nullopt;
73       break;
74     case kDataIDFunctionSelectors:
75       if (!result.function_selectors.Decode(data, offset_ptr, strtab))
76         return std::nullopt;
77       break;
78     case kDataIDFunctionObjcClassSelectors:
79       if (!result.objc_class_selectors.Decode(data, offset_ptr, strtab))
80         return std::nullopt;
81       break;
82     case kDataIDGlobals:
83       if (!result.globals.Decode(data, offset_ptr, strtab))
84         return std::nullopt;
85       break;
86     case kDataIDTypes:
87       if (!result.types.Decode(data, offset_ptr, strtab))
88         return std::nullopt;
89       break;
90     case kDataIDNamespaces:
91       if (!result.namespaces.Decode(data, offset_ptr, strtab))
92         return std::nullopt;
93       break;
94     case kDataIDEnd:
95       // We got to the end of our NameToDIE encodings.
96       return std::move(result);
97       break;
98     }
99   }
100 }
101 
EncodeIndexSet(const IndexSet<NameToDIE> & set,DataEncoder & encoder)102 void plugin::dwarf::EncodeIndexSet(const IndexSet<NameToDIE> &set,
103                                    DataEncoder &encoder) {
104   ConstStringTable strtab;
105 
106   // Encoder the DWARF index into a separate encoder first. This allows us
107   // gather all of the strings we willl need in "strtab" as we will need to
108   // write the string table out before the symbol table.
109   DataEncoder index_encoder(encoder.GetByteOrder(),
110                             encoder.GetAddressByteSize());
111 
112   index_encoder.AppendData(kIdentifierManualDWARFIndex);
113   // Encode the data version.
114   index_encoder.AppendU32(CURRENT_CACHE_VERSION);
115 
116   if (!set.function_basenames.IsEmpty()) {
117     index_encoder.AppendU8(kDataIDFunctionBasenames);
118     set.function_basenames.Encode(index_encoder, strtab);
119   }
120   if (!set.function_fullnames.IsEmpty()) {
121     index_encoder.AppendU8(kDataIDFunctionFullnames);
122     set.function_fullnames.Encode(index_encoder, strtab);
123   }
124   if (!set.function_methods.IsEmpty()) {
125     index_encoder.AppendU8(kDataIDFunctionMethods);
126     set.function_methods.Encode(index_encoder, strtab);
127   }
128   if (!set.function_selectors.IsEmpty()) {
129     index_encoder.AppendU8(kDataIDFunctionSelectors);
130     set.function_selectors.Encode(index_encoder, strtab);
131   }
132   if (!set.objc_class_selectors.IsEmpty()) {
133     index_encoder.AppendU8(kDataIDFunctionObjcClassSelectors);
134     set.objc_class_selectors.Encode(index_encoder, strtab);
135   }
136   if (!set.globals.IsEmpty()) {
137     index_encoder.AppendU8(kDataIDGlobals);
138     set.globals.Encode(index_encoder, strtab);
139   }
140   if (!set.types.IsEmpty()) {
141     index_encoder.AppendU8(kDataIDTypes);
142     set.types.Encode(index_encoder, strtab);
143   }
144   if (!set.namespaces.IsEmpty()) {
145     index_encoder.AppendU8(kDataIDNamespaces);
146     set.namespaces.Encode(index_encoder, strtab);
147   }
148   index_encoder.AppendU8(kDataIDEnd);
149 
150   // Now that all strings have been gathered, we will emit the string table.
151   strtab.Encode(encoder);
152   // Followed by the symbol table data.
153   encoder.AppendData(index_encoder.GetData());
154 }
155