1 //===-- DWARFIndexCachingTest.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/DIERef.h"
10 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
11 #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
12 #include "Plugins/SymbolFile/DWARF/NameToDIE.h"
13 #include "TestingSupport/Symbol/YAMLModuleTester.h"
14 #include "lldb/Core/DataFileCache.h"
15 #include "lldb/Core/ModuleList.h"
16 #include "lldb/Utility/DataEncoder.h"
17 #include "lldb/Utility/DataExtractor.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
EncodeDecode(const DIERef & object,ByteOrder byte_order)25 static void EncodeDecode(const DIERef &object, ByteOrder byte_order) {
26 const uint8_t addr_size = 8;
27 DataEncoder encoder(byte_order, addr_size);
28 object.Encode(encoder);
29 llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
30 DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
31 offset_t data_offset = 0;
32 EXPECT_EQ(object, DIERef::Decode(data, &data_offset));
33 }
34
EncodeDecode(const DIERef & object)35 static void EncodeDecode(const DIERef &object) {
36 EncodeDecode(object, eByteOrderLittle);
37 EncodeDecode(object, eByteOrderBig);
38 }
39
TEST(DWARFIndexCachingTest,DIERefEncodeDecode)40 TEST(DWARFIndexCachingTest, DIERefEncodeDecode) {
41 // Tests DIERef::Encode(...) and DIERef::Decode(...)
42 EncodeDecode(DIERef(llvm::None, DIERef::Section::DebugInfo, 0x11223344));
43 EncodeDecode(DIERef(llvm::None, DIERef::Section::DebugTypes, 0x11223344));
44 EncodeDecode(DIERef(100, DIERef::Section::DebugInfo, 0x11223344));
45 EncodeDecode(DIERef(200, DIERef::Section::DebugTypes, 0x11223344));
46 }
47
EncodeDecode(const NameToDIE & object,ByteOrder byte_order)48 static void EncodeDecode(const NameToDIE &object, ByteOrder byte_order) {
49 const uint8_t addr_size = 8;
50 DataEncoder encoder(byte_order, addr_size);
51 DataEncoder strtab_encoder(byte_order, addr_size);
52 ConstStringTable const_strtab;
53
54 object.Encode(encoder, const_strtab);
55
56 llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
57 DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
58
59 const_strtab.Encode(strtab_encoder);
60 llvm::ArrayRef<uint8_t> strtab_bytes = strtab_encoder.GetData();
61 DataExtractor strtab_data(strtab_bytes.data(), strtab_bytes.size(),
62 byte_order, addr_size);
63 StringTableReader strtab_reader;
64 offset_t strtab_data_offset = 0;
65 ASSERT_EQ(strtab_reader.Decode(strtab_data, &strtab_data_offset), true);
66
67 NameToDIE decoded_object;
68 offset_t data_offset = 0;
69 decoded_object.Decode(data, &data_offset, strtab_reader);
70 EXPECT_EQ(object, decoded_object);
71 }
72
EncodeDecode(const NameToDIE & object)73 static void EncodeDecode(const NameToDIE &object) {
74 EncodeDecode(object, eByteOrderLittle);
75 EncodeDecode(object, eByteOrderBig);
76 }
77
TEST(DWARFIndexCachingTest,NameToDIEEncodeDecode)78 TEST(DWARFIndexCachingTest, NameToDIEEncodeDecode) {
79 NameToDIE map;
80 // Make sure an empty NameToDIE map encodes and decodes correctly.
81 EncodeDecode(map);
82 map.Insert(ConstString("hello"),
83 DIERef(llvm::None, DIERef::Section::DebugInfo, 0x11223344));
84 map.Insert(ConstString("workd"),
85 DIERef(100, DIERef::Section::DebugInfo, 0x11223344));
86 map.Finalize();
87 // Make sure a valid NameToDIE map encodes and decodes correctly.
88 EncodeDecode(map);
89 }
90
EncodeDecode(const ManualDWARFIndex::IndexSet & object,ByteOrder byte_order)91 static void EncodeDecode(const ManualDWARFIndex::IndexSet &object,
92 ByteOrder byte_order) {
93 const uint8_t addr_size = 8;
94 DataEncoder encoder(byte_order, addr_size);
95 DataEncoder strtab_encoder(byte_order, addr_size);
96 object.Encode(encoder);
97 llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
98 DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
99 ManualDWARFIndex::IndexSet decoded_object;
100 offset_t data_offset = 0;
101 decoded_object.Decode(data, &data_offset);
102 EXPECT_TRUE(object == decoded_object);
103 }
104
EncodeDecode(const ManualDWARFIndex::IndexSet & object)105 static void EncodeDecode(const ManualDWARFIndex::IndexSet &object) {
106 EncodeDecode(object, eByteOrderLittle);
107 EncodeDecode(object, eByteOrderBig);
108 }
109
TEST(DWARFIndexCachingTest,ManualDWARFIndexIndexSetEncodeDecode)110 TEST(DWARFIndexCachingTest, ManualDWARFIndexIndexSetEncodeDecode) {
111 ManualDWARFIndex::IndexSet set;
112 // Make sure empty IndexSet can be encoded and decoded correctly
113 EncodeDecode(set);
114
115 dw_offset_t die_offset = 0;
116 // Make sure an IndexSet with only items in IndexSet::function_basenames can
117 // be encoded and decoded correctly.
118 set.function_basenames.Insert(
119 ConstString("a"),
120 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
121 EncodeDecode(set);
122 set.function_basenames.Clear();
123 // Make sure an IndexSet with only items in IndexSet::function_fullnames can
124 // be encoded and decoded correctly.
125 set.function_fullnames.Insert(
126 ConstString("a"),
127 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
128 EncodeDecode(set);
129 set.function_fullnames.Clear();
130 // Make sure an IndexSet with only items in IndexSet::function_methods can
131 // be encoded and decoded correctly.
132 set.function_methods.Insert(
133 ConstString("a"),
134 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
135 EncodeDecode(set);
136 set.function_methods.Clear();
137 // Make sure an IndexSet with only items in IndexSet::function_selectors can
138 // be encoded and decoded correctly.
139 set.function_selectors.Insert(
140 ConstString("a"),
141 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
142 EncodeDecode(set);
143 set.function_selectors.Clear();
144 // Make sure an IndexSet with only items in IndexSet::objc_class_selectors can
145 // be encoded and decoded correctly.
146 set.objc_class_selectors.Insert(
147 ConstString("a"),
148 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
149 EncodeDecode(set);
150 set.objc_class_selectors.Clear();
151 // Make sure an IndexSet with only items in IndexSet::globals can
152 // be encoded and decoded correctly.
153 set.globals.Insert(
154 ConstString("a"),
155 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
156 EncodeDecode(set);
157 set.globals.Clear();
158 // Make sure an IndexSet with only items in IndexSet::types can
159 // be encoded and decoded correctly.
160 set.types.Insert(
161 ConstString("a"),
162 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
163 EncodeDecode(set);
164 set.types.Clear();
165 // Make sure an IndexSet with only items in IndexSet::namespaces can
166 // be encoded and decoded correctly.
167 set.namespaces.Insert(
168 ConstString("a"),
169 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
170 EncodeDecode(set);
171 set.namespaces.Clear();
172 // Make sure that an IndexSet with item in all NameToDIE maps can be
173 // be encoded and decoded correctly.
174 set.function_basenames.Insert(
175 ConstString("a"),
176 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
177 set.function_fullnames.Insert(
178 ConstString("b"),
179 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
180 set.function_methods.Insert(
181 ConstString("c"),
182 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
183 set.function_selectors.Insert(
184 ConstString("d"),
185 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
186 set.objc_class_selectors.Insert(
187 ConstString("e"),
188 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
189 set.globals.Insert(
190 ConstString("f"),
191 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
192 set.types.Insert(
193 ConstString("g"),
194 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
195 set.namespaces.Insert(
196 ConstString("h"),
197 DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
198 EncodeDecode(set);
199 }
200
EncodeDecode(const CacheSignature & object,ByteOrder byte_order,bool encode_result)201 static void EncodeDecode(const CacheSignature &object, ByteOrder byte_order,
202 bool encode_result) {
203 const uint8_t addr_size = 8;
204 DataEncoder encoder(byte_order, addr_size);
205 EXPECT_EQ(encode_result, object.Encode(encoder));
206 if (!encode_result)
207 return;
208 llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
209 DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
210 offset_t data_offset = 0;
211 CacheSignature decoded_object;
212 EXPECT_TRUE(decoded_object.Decode(data, &data_offset));
213 EXPECT_EQ(object, decoded_object);
214 }
215
EncodeDecode(const CacheSignature & object,bool encode_result)216 static void EncodeDecode(const CacheSignature &object, bool encode_result) {
217 EncodeDecode(object, eByteOrderLittle, encode_result);
218 EncodeDecode(object, eByteOrderBig, encode_result);
219 }
220
TEST(DWARFIndexCachingTest,CacheSignatureTests)221 TEST(DWARFIndexCachingTest, CacheSignatureTests) {
222 CacheSignature sig;
223 // A cache signature is only considered valid if it has a UUID.
224 sig.m_mod_time = 0x12345678;
225 EXPECT_FALSE(sig.IsValid());
226 EncodeDecode(sig, /*encode_result=*/false);
227 sig.Clear();
228
229 sig.m_obj_mod_time = 0x12345678;
230 EXPECT_FALSE(sig.IsValid());
231 EncodeDecode(sig, /*encode_result=*/false);
232 sig.Clear();
233
234 sig.m_uuid = UUID::fromData("@\x00\x11\x22\x33\x44\x55\x66\x77", 8);
235 EXPECT_TRUE(sig.IsValid());
236 EncodeDecode(sig, /*encode_result=*/true);
237 sig.m_mod_time = 0x12345678;
238 EXPECT_TRUE(sig.IsValid());
239 EncodeDecode(sig, /*encode_result=*/true);
240 sig.m_obj_mod_time = 0x456789ab;
241 EXPECT_TRUE(sig.IsValid());
242 EncodeDecode(sig, /*encode_result=*/true);
243 sig.m_mod_time = llvm::None;
244 EXPECT_TRUE(sig.IsValid());
245 EncodeDecode(sig, /*encode_result=*/true);
246
247 // Recent changes do not allow cache signatures with only a modification time
248 // or object modification time, so make sure if we try to decode such a cache
249 // file that we fail. This verifies that if we try to load an previously
250 // valid cache file where the signature is insufficient, that we will fail to
251 // decode and load these cache files.
252 DataEncoder encoder(eByteOrderLittle, /*addr_size=*/8);
253 encoder.AppendU8(2); // eSignatureModTime
254 encoder.AppendU32(0x12345678);
255 encoder.AppendU8(255); // eSignatureEnd
256
257 llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
258 DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle,
259 /*addr_size=*/8);
260 offset_t data_offset = 0;
261
262 // Make sure we fail to decode a CacheSignature with only a mod time
263 EXPECT_FALSE(sig.Decode(data, &data_offset));
264
265 // Change the signature data to contain only a eSignatureObjectModTime and
266 // make sure decoding fails as well.
267 encoder.PutU8(/*offset=*/0, 3); // eSignatureObjectModTime
268 data_offset = 0;
269 EXPECT_FALSE(sig.Decode(data, &data_offset));
270
271 }
272