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>> |
41 | plugin::dwarf::(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, length: 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 | |
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(data: kIdentifierManualDWARFIndex); |
113 | // Encode the data version. |
114 | index_encoder.AppendU32(value: CURRENT_CACHE_VERSION); |
115 | |
116 | if (!set.function_basenames.IsEmpty()) { |
117 | index_encoder.AppendU8(value: kDataIDFunctionBasenames); |
118 | set.function_basenames.Encode(encoder&: index_encoder, strtab); |
119 | } |
120 | if (!set.function_fullnames.IsEmpty()) { |
121 | index_encoder.AppendU8(value: kDataIDFunctionFullnames); |
122 | set.function_fullnames.Encode(encoder&: index_encoder, strtab); |
123 | } |
124 | if (!set.function_methods.IsEmpty()) { |
125 | index_encoder.AppendU8(value: kDataIDFunctionMethods); |
126 | set.function_methods.Encode(encoder&: index_encoder, strtab); |
127 | } |
128 | if (!set.function_selectors.IsEmpty()) { |
129 | index_encoder.AppendU8(value: kDataIDFunctionSelectors); |
130 | set.function_selectors.Encode(encoder&: index_encoder, strtab); |
131 | } |
132 | if (!set.objc_class_selectors.IsEmpty()) { |
133 | index_encoder.AppendU8(value: kDataIDFunctionObjcClassSelectors); |
134 | set.objc_class_selectors.Encode(encoder&: index_encoder, strtab); |
135 | } |
136 | if (!set.globals.IsEmpty()) { |
137 | index_encoder.AppendU8(value: kDataIDGlobals); |
138 | set.globals.Encode(encoder&: index_encoder, strtab); |
139 | } |
140 | if (!set.types.IsEmpty()) { |
141 | index_encoder.AppendU8(value: kDataIDTypes); |
142 | set.types.Encode(encoder&: index_encoder, strtab); |
143 | } |
144 | if (!set.namespaces.IsEmpty()) { |
145 | index_encoder.AppendU8(value: kDataIDNamespaces); |
146 | set.namespaces.Encode(encoder&: index_encoder, strtab); |
147 | } |
148 | index_encoder.AppendU8(value: 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(data: index_encoder.GetData()); |
154 | } |
155 | |