1a2154b19SGreg Clayton //===-- DWARFIndexCachingTest.cpp -------------------------------------=---===//
2a2154b19SGreg Clayton //
3a2154b19SGreg Clayton // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a2154b19SGreg Clayton // See https://llvm.org/LICENSE.txt for license information.
5a2154b19SGreg Clayton // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a2154b19SGreg Clayton //
7a2154b19SGreg Clayton //===----------------------------------------------------------------------===//
8a2154b19SGreg Clayton
9a2154b19SGreg Clayton #include "Plugins/SymbolFile/DWARF/DIERef.h"
10a2154b19SGreg Clayton #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
11a2154b19SGreg Clayton #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
12a2154b19SGreg Clayton #include "Plugins/SymbolFile/DWARF/NameToDIE.h"
13a2154b19SGreg Clayton #include "TestingSupport/Symbol/YAMLModuleTester.h"
14a2154b19SGreg Clayton #include "lldb/Core/DataFileCache.h"
15a2154b19SGreg Clayton #include "lldb/Core/ModuleList.h"
16a2154b19SGreg Clayton #include "lldb/Utility/DataEncoder.h"
17a2154b19SGreg Clayton #include "lldb/Utility/DataExtractor.h"
18a2154b19SGreg Clayton #include "llvm/ADT/STLExtras.h"
19a2154b19SGreg Clayton #include "gmock/gmock.h"
20a2154b19SGreg Clayton #include "gtest/gtest.h"
21a2154b19SGreg Clayton
22a2154b19SGreg Clayton using namespace lldb;
23a2154b19SGreg Clayton using namespace lldb_private;
24*a669a237Swalter erquinigo using namespace lldb_private::plugin::dwarf;
25a2154b19SGreg Clayton
EncodeDecode(const DIERef & object,ByteOrder byte_order)26a2154b19SGreg Clayton static void EncodeDecode(const DIERef &object, ByteOrder byte_order) {
27a2154b19SGreg Clayton const uint8_t addr_size = 8;
28a2154b19SGreg Clayton DataEncoder encoder(byte_order, addr_size);
29a2154b19SGreg Clayton object.Encode(encoder);
30a2154b19SGreg Clayton llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
31a2154b19SGreg Clayton DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
32a2154b19SGreg Clayton offset_t data_offset = 0;
33a2154b19SGreg Clayton EXPECT_EQ(object, DIERef::Decode(data, &data_offset));
34a2154b19SGreg Clayton }
35a2154b19SGreg Clayton
EncodeDecode(const DIERef & object)36a2154b19SGreg Clayton static void EncodeDecode(const DIERef &object) {
37a2154b19SGreg Clayton EncodeDecode(object, eByteOrderLittle);
38a2154b19SGreg Clayton EncodeDecode(object, eByteOrderBig);
39a2154b19SGreg Clayton }
40a2154b19SGreg Clayton
TEST(DWARFIndexCachingTest,DIERefEncodeDecode)41a2154b19SGreg Clayton TEST(DWARFIndexCachingTest, DIERefEncodeDecode) {
42a2154b19SGreg Clayton // Tests DIERef::Encode(...) and DIERef::Decode(...)
43d2a6114fSKazu Hirata EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugInfo, 0x11223344));
44d2a6114fSKazu Hirata EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugTypes, 0x11223344));
45a2154b19SGreg Clayton EncodeDecode(DIERef(100, DIERef::Section::DebugInfo, 0x11223344));
46a2154b19SGreg Clayton EncodeDecode(DIERef(200, DIERef::Section::DebugTypes, 0x11223344));
47a2154b19SGreg Clayton }
48a2154b19SGreg Clayton
TEST(DWARFIndexCachingTest,DIERefEncodeDecodeMax)4934a8e6eeSAlexander Yermolovich TEST(DWARFIndexCachingTest, DIERefEncodeDecodeMax) {
5034a8e6eeSAlexander Yermolovich // Tests DIERef::Encode(...) and DIERef::Decode(...)
5134a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugInfo,
5234a8e6eeSAlexander Yermolovich DIERef::k_die_offset_mask - 1));
5334a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugTypes,
5434a8e6eeSAlexander Yermolovich DIERef::k_die_offset_mask - 1));
5534a8e6eeSAlexander Yermolovich EncodeDecode(
5634a8e6eeSAlexander Yermolovich DIERef(100, DIERef::Section::DebugInfo, DIERef::k_die_offset_mask - 1));
5734a8e6eeSAlexander Yermolovich EncodeDecode(
5834a8e6eeSAlexander Yermolovich DIERef(200, DIERef::Section::DebugTypes, DIERef::k_die_offset_mask - 1));
5934a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugInfo,
6034a8e6eeSAlexander Yermolovich DIERef::k_file_index_mask));
6134a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugTypes,
6234a8e6eeSAlexander Yermolovich DIERef::k_file_index_mask));
6334a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugInfo,
6434a8e6eeSAlexander Yermolovich 0x11223344));
6534a8e6eeSAlexander Yermolovich EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugTypes,
6634a8e6eeSAlexander Yermolovich 0x11223344));
6734a8e6eeSAlexander Yermolovich }
6834a8e6eeSAlexander Yermolovich
EncodeDecode(const NameToDIE & object,ByteOrder byte_order)69a2154b19SGreg Clayton static void EncodeDecode(const NameToDIE &object, ByteOrder byte_order) {
70a2154b19SGreg Clayton const uint8_t addr_size = 8;
71a2154b19SGreg Clayton DataEncoder encoder(byte_order, addr_size);
72a2154b19SGreg Clayton DataEncoder strtab_encoder(byte_order, addr_size);
73a2154b19SGreg Clayton ConstStringTable const_strtab;
74a2154b19SGreg Clayton
75a2154b19SGreg Clayton object.Encode(encoder, const_strtab);
76a2154b19SGreg Clayton
77a2154b19SGreg Clayton llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
78a2154b19SGreg Clayton DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
79a2154b19SGreg Clayton
80a2154b19SGreg Clayton const_strtab.Encode(strtab_encoder);
81a2154b19SGreg Clayton llvm::ArrayRef<uint8_t> strtab_bytes = strtab_encoder.GetData();
82a2154b19SGreg Clayton DataExtractor strtab_data(strtab_bytes.data(), strtab_bytes.size(),
83a2154b19SGreg Clayton byte_order, addr_size);
84a2154b19SGreg Clayton StringTableReader strtab_reader;
85a2154b19SGreg Clayton offset_t strtab_data_offset = 0;
86a2154b19SGreg Clayton ASSERT_EQ(strtab_reader.Decode(strtab_data, &strtab_data_offset), true);
87a2154b19SGreg Clayton
88a2154b19SGreg Clayton NameToDIE decoded_object;
89a2154b19SGreg Clayton offset_t data_offset = 0;
90a2154b19SGreg Clayton decoded_object.Decode(data, &data_offset, strtab_reader);
9151e72570SPavel Labath EXPECT_EQ(object, decoded_object);
92a2154b19SGreg Clayton }
93a2154b19SGreg Clayton
EncodeDecode(const NameToDIE & object)94a2154b19SGreg Clayton static void EncodeDecode(const NameToDIE &object) {
95a2154b19SGreg Clayton EncodeDecode(object, eByteOrderLittle);
96a2154b19SGreg Clayton EncodeDecode(object, eByteOrderBig);
97a2154b19SGreg Clayton }
98a2154b19SGreg Clayton
TEST(DWARFIndexCachingTest,NameToDIEEncodeDecode)99a2154b19SGreg Clayton TEST(DWARFIndexCachingTest, NameToDIEEncodeDecode) {
100a2154b19SGreg Clayton NameToDIE map;
101a2154b19SGreg Clayton // Make sure an empty NameToDIE map encodes and decodes correctly.
102a2154b19SGreg Clayton EncodeDecode(map);
103a2154b19SGreg Clayton map.Insert(ConstString("hello"),
104d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, 0x11223344));
105a2154b19SGreg Clayton map.Insert(ConstString("workd"),
106a2154b19SGreg Clayton DIERef(100, DIERef::Section::DebugInfo, 0x11223344));
10751e72570SPavel Labath map.Finalize();
108a2154b19SGreg Clayton // Make sure a valid NameToDIE map encodes and decodes correctly.
109a2154b19SGreg Clayton EncodeDecode(map);
110a2154b19SGreg Clayton }
111a2154b19SGreg Clayton
EncodeDecode(const ManualDWARFIndex::IndexSet & object,ByteOrder byte_order)112a2154b19SGreg Clayton static void EncodeDecode(const ManualDWARFIndex::IndexSet &object,
113a2154b19SGreg Clayton ByteOrder byte_order) {
114a2154b19SGreg Clayton const uint8_t addr_size = 8;
115a2154b19SGreg Clayton DataEncoder encoder(byte_order, addr_size);
116a2154b19SGreg Clayton DataEncoder strtab_encoder(byte_order, addr_size);
117a2154b19SGreg Clayton object.Encode(encoder);
118a2154b19SGreg Clayton llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
119a2154b19SGreg Clayton DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
120a2154b19SGreg Clayton ManualDWARFIndex::IndexSet decoded_object;
121a2154b19SGreg Clayton offset_t data_offset = 0;
122a2154b19SGreg Clayton decoded_object.Decode(data, &data_offset);
123a2154b19SGreg Clayton EXPECT_TRUE(object == decoded_object);
124a2154b19SGreg Clayton }
125a2154b19SGreg Clayton
EncodeDecode(const ManualDWARFIndex::IndexSet & object)126a2154b19SGreg Clayton static void EncodeDecode(const ManualDWARFIndex::IndexSet &object) {
127a2154b19SGreg Clayton EncodeDecode(object, eByteOrderLittle);
128a2154b19SGreg Clayton EncodeDecode(object, eByteOrderBig);
129a2154b19SGreg Clayton }
130a2154b19SGreg Clayton
TEST(DWARFIndexCachingTest,ManualDWARFIndexIndexSetEncodeDecode)131a2154b19SGreg Clayton TEST(DWARFIndexCachingTest, ManualDWARFIndexIndexSetEncodeDecode) {
132a2154b19SGreg Clayton ManualDWARFIndex::IndexSet set;
133a2154b19SGreg Clayton // Make sure empty IndexSet can be encoded and decoded correctly
134a2154b19SGreg Clayton EncodeDecode(set);
135a2154b19SGreg Clayton
136a2154b19SGreg Clayton dw_offset_t die_offset = 0;
137a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::function_basenames can
138a2154b19SGreg Clayton // be encoded and decoded correctly.
139a2154b19SGreg Clayton set.function_basenames.Insert(
140a2154b19SGreg Clayton ConstString("a"),
141d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
142a2154b19SGreg Clayton EncodeDecode(set);
143a2154b19SGreg Clayton set.function_basenames.Clear();
144a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::function_fullnames can
145a2154b19SGreg Clayton // be encoded and decoded correctly.
146a2154b19SGreg Clayton set.function_fullnames.Insert(
147a2154b19SGreg Clayton ConstString("a"),
148d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
149a2154b19SGreg Clayton EncodeDecode(set);
150a2154b19SGreg Clayton set.function_fullnames.Clear();
151a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::function_methods can
152a2154b19SGreg Clayton // be encoded and decoded correctly.
153a2154b19SGreg Clayton set.function_methods.Insert(
154a2154b19SGreg Clayton ConstString("a"),
155d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
156a2154b19SGreg Clayton EncodeDecode(set);
157a2154b19SGreg Clayton set.function_methods.Clear();
158a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::function_selectors can
159a2154b19SGreg Clayton // be encoded and decoded correctly.
160a2154b19SGreg Clayton set.function_selectors.Insert(
161a2154b19SGreg Clayton ConstString("a"),
162d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
163a2154b19SGreg Clayton EncodeDecode(set);
164a2154b19SGreg Clayton set.function_selectors.Clear();
165a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::objc_class_selectors can
166a2154b19SGreg Clayton // be encoded and decoded correctly.
167a2154b19SGreg Clayton set.objc_class_selectors.Insert(
168a2154b19SGreg Clayton ConstString("a"),
169d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
170a2154b19SGreg Clayton EncodeDecode(set);
171a2154b19SGreg Clayton set.objc_class_selectors.Clear();
172a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::globals can
173a2154b19SGreg Clayton // be encoded and decoded correctly.
174a2154b19SGreg Clayton set.globals.Insert(
175a2154b19SGreg Clayton ConstString("a"),
176d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
177a2154b19SGreg Clayton EncodeDecode(set);
178a2154b19SGreg Clayton set.globals.Clear();
179a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::types can
180a2154b19SGreg Clayton // be encoded and decoded correctly.
181a2154b19SGreg Clayton set.types.Insert(
182a2154b19SGreg Clayton ConstString("a"),
183d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
184a2154b19SGreg Clayton EncodeDecode(set);
185a2154b19SGreg Clayton set.types.Clear();
186a2154b19SGreg Clayton // Make sure an IndexSet with only items in IndexSet::namespaces can
187a2154b19SGreg Clayton // be encoded and decoded correctly.
188a2154b19SGreg Clayton set.namespaces.Insert(
189a2154b19SGreg Clayton ConstString("a"),
190d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
191a2154b19SGreg Clayton EncodeDecode(set);
192a2154b19SGreg Clayton set.namespaces.Clear();
193a2154b19SGreg Clayton // Make sure that an IndexSet with item in all NameToDIE maps can be
194a2154b19SGreg Clayton // be encoded and decoded correctly.
195a2154b19SGreg Clayton set.function_basenames.Insert(
196a2154b19SGreg Clayton ConstString("a"),
197d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
198a2154b19SGreg Clayton set.function_fullnames.Insert(
199a2154b19SGreg Clayton ConstString("b"),
200d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
201a2154b19SGreg Clayton set.function_methods.Insert(
202a2154b19SGreg Clayton ConstString("c"),
203d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
204a2154b19SGreg Clayton set.function_selectors.Insert(
205a2154b19SGreg Clayton ConstString("d"),
206d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
207a2154b19SGreg Clayton set.objc_class_selectors.Insert(
208a2154b19SGreg Clayton ConstString("e"),
209d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
210a2154b19SGreg Clayton set.globals.Insert(
211a2154b19SGreg Clayton ConstString("f"),
212d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
213a2154b19SGreg Clayton set.types.Insert(
214a2154b19SGreg Clayton ConstString("g"),
215d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
216a2154b19SGreg Clayton set.namespaces.Insert(
217a2154b19SGreg Clayton ConstString("h"),
218d2a6114fSKazu Hirata DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));
219a2154b19SGreg Clayton EncodeDecode(set);
220a2154b19SGreg Clayton }
221b6087ba7SGreg Clayton
EncodeDecode(const CacheSignature & object,ByteOrder byte_order,bool encode_result)222b6087ba7SGreg Clayton static void EncodeDecode(const CacheSignature &object, ByteOrder byte_order,
223b6087ba7SGreg Clayton bool encode_result) {
224b6087ba7SGreg Clayton const uint8_t addr_size = 8;
225b6087ba7SGreg Clayton DataEncoder encoder(byte_order, addr_size);
226b6087ba7SGreg Clayton EXPECT_EQ(encode_result, object.Encode(encoder));
227b6087ba7SGreg Clayton if (!encode_result)
228b6087ba7SGreg Clayton return;
229b6087ba7SGreg Clayton llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
230b6087ba7SGreg Clayton DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
231b6087ba7SGreg Clayton offset_t data_offset = 0;
232b6087ba7SGreg Clayton CacheSignature decoded_object;
233b6087ba7SGreg Clayton EXPECT_TRUE(decoded_object.Decode(data, &data_offset));
234b6087ba7SGreg Clayton EXPECT_EQ(object, decoded_object);
235b6087ba7SGreg Clayton }
236b6087ba7SGreg Clayton
EncodeDecode(const CacheSignature & object,bool encode_result)237b6087ba7SGreg Clayton static void EncodeDecode(const CacheSignature &object, bool encode_result) {
238b6087ba7SGreg Clayton EncodeDecode(object, eByteOrderLittle, encode_result);
239b6087ba7SGreg Clayton EncodeDecode(object, eByteOrderBig, encode_result);
240b6087ba7SGreg Clayton }
241b6087ba7SGreg Clayton
TEST(DWARFIndexCachingTest,CacheSignatureTests)242b6087ba7SGreg Clayton TEST(DWARFIndexCachingTest, CacheSignatureTests) {
243b6087ba7SGreg Clayton CacheSignature sig;
244b6087ba7SGreg Clayton // A cache signature is only considered valid if it has a UUID.
245b6087ba7SGreg Clayton sig.m_mod_time = 0x12345678;
246b6087ba7SGreg Clayton EXPECT_FALSE(sig.IsValid());
247b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/false);
248b6087ba7SGreg Clayton sig.Clear();
249b6087ba7SGreg Clayton
250b6087ba7SGreg Clayton sig.m_obj_mod_time = 0x12345678;
251b6087ba7SGreg Clayton EXPECT_FALSE(sig.IsValid());
252b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/false);
253b6087ba7SGreg Clayton sig.Clear();
254b6087ba7SGreg Clayton
2555ad6ed0eSJim Ingham sig.m_uuid = UUID("@\x00\x11\x22\x33\x44\x55\x66\x77", 8);
256b6087ba7SGreg Clayton EXPECT_TRUE(sig.IsValid());
257b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/true);
258b6087ba7SGreg Clayton sig.m_mod_time = 0x12345678;
259b6087ba7SGreg Clayton EXPECT_TRUE(sig.IsValid());
260b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/true);
261b6087ba7SGreg Clayton sig.m_obj_mod_time = 0x456789ab;
262b6087ba7SGreg Clayton EXPECT_TRUE(sig.IsValid());
263b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/true);
264d2a6114fSKazu Hirata sig.m_mod_time = std::nullopt;
265b6087ba7SGreg Clayton EXPECT_TRUE(sig.IsValid());
266b6087ba7SGreg Clayton EncodeDecode(sig, /*encode_result=*/true);
267b6087ba7SGreg Clayton
268b6087ba7SGreg Clayton // Recent changes do not allow cache signatures with only a modification time
269b6087ba7SGreg Clayton // or object modification time, so make sure if we try to decode such a cache
270b6087ba7SGreg Clayton // file that we fail. This verifies that if we try to load an previously
271b6087ba7SGreg Clayton // valid cache file where the signature is insufficient, that we will fail to
272b6087ba7SGreg Clayton // decode and load these cache files.
273b6087ba7SGreg Clayton DataEncoder encoder(eByteOrderLittle, /*addr_size=*/8);
274b6087ba7SGreg Clayton encoder.AppendU8(2); // eSignatureModTime
275b6087ba7SGreg Clayton encoder.AppendU32(0x12345678);
276b6087ba7SGreg Clayton encoder.AppendU8(255); // eSignatureEnd
277b6087ba7SGreg Clayton
278b6087ba7SGreg Clayton llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
279b6087ba7SGreg Clayton DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle,
280b6087ba7SGreg Clayton /*addr_size=*/8);
281b6087ba7SGreg Clayton offset_t data_offset = 0;
282b6087ba7SGreg Clayton
283b6087ba7SGreg Clayton // Make sure we fail to decode a CacheSignature with only a mod time
284b6087ba7SGreg Clayton EXPECT_FALSE(sig.Decode(data, &data_offset));
285b6087ba7SGreg Clayton
286b6087ba7SGreg Clayton // Change the signature data to contain only a eSignatureObjectModTime and
287b6087ba7SGreg Clayton // make sure decoding fails as well.
288b6087ba7SGreg Clayton encoder.PutU8(/*offset=*/0, 3); // eSignatureObjectModTime
289b6087ba7SGreg Clayton data_offset = 0;
290b6087ba7SGreg Clayton EXPECT_FALSE(sig.Decode(data, &data_offset));
291b6087ba7SGreg Clayton
292b6087ba7SGreg Clayton }
293