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 
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 
35 static void EncodeDecode(const DIERef &object) {
36   EncodeDecode(object, eByteOrderLittle);
37   EncodeDecode(object, eByteOrderBig);
38 }
39 
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 
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_TRUE(object == decoded_object);
71 }
72 
73 static void EncodeDecode(const NameToDIE &object) {
74   EncodeDecode(object, eByteOrderLittle);
75   EncodeDecode(object, eByteOrderBig);
76 }
77 
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   // Make sure a valid NameToDIE map encodes and decodes correctly.
87   EncodeDecode(map);
88 }
89 
90 static void EncodeDecode(const ManualDWARFIndex::IndexSet &object,
91                          ByteOrder byte_order) {
92   const uint8_t addr_size = 8;
93   DataEncoder encoder(byte_order, addr_size);
94   DataEncoder strtab_encoder(byte_order, addr_size);
95   object.Encode(encoder);
96   llvm::ArrayRef<uint8_t> bytes = encoder.GetData();
97   DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
98   ManualDWARFIndex::IndexSet decoded_object;
99   offset_t data_offset = 0;
100   decoded_object.Decode(data, &data_offset);
101   EXPECT_TRUE(object == decoded_object);
102 }
103 
104 static void EncodeDecode(const ManualDWARFIndex::IndexSet &object) {
105   EncodeDecode(object, eByteOrderLittle);
106   EncodeDecode(object, eByteOrderBig);
107 }
108 
109 TEST(DWARFIndexCachingTest, ManualDWARFIndexIndexSetEncodeDecode) {
110   ManualDWARFIndex::IndexSet set;
111   // Make sure empty IndexSet can be encoded and decoded correctly
112   EncodeDecode(set);
113 
114   dw_offset_t die_offset = 0;
115   // Make sure an IndexSet with only items in IndexSet::function_basenames can
116   // be encoded and decoded correctly.
117   set.function_basenames.Insert(
118       ConstString("a"),
119       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
120   EncodeDecode(set);
121   set.function_basenames.Clear();
122   // Make sure an IndexSet with only items in IndexSet::function_fullnames can
123   // be encoded and decoded correctly.
124   set.function_fullnames.Insert(
125       ConstString("a"),
126       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
127   EncodeDecode(set);
128   set.function_fullnames.Clear();
129   // Make sure an IndexSet with only items in IndexSet::function_methods can
130   // be encoded and decoded correctly.
131   set.function_methods.Insert(
132       ConstString("a"),
133       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
134   EncodeDecode(set);
135   set.function_methods.Clear();
136   // Make sure an IndexSet with only items in IndexSet::function_selectors can
137   // be encoded and decoded correctly.
138   set.function_selectors.Insert(
139       ConstString("a"),
140       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
141   EncodeDecode(set);
142   set.function_selectors.Clear();
143   // Make sure an IndexSet with only items in IndexSet::objc_class_selectors can
144   // be encoded and decoded correctly.
145   set.objc_class_selectors.Insert(
146       ConstString("a"),
147       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
148   EncodeDecode(set);
149   set.objc_class_selectors.Clear();
150   // Make sure an IndexSet with only items in IndexSet::globals can
151   // be encoded and decoded correctly.
152   set.globals.Insert(
153       ConstString("a"),
154       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
155   EncodeDecode(set);
156   set.globals.Clear();
157   // Make sure an IndexSet with only items in IndexSet::types can
158   // be encoded and decoded correctly.
159   set.types.Insert(
160       ConstString("a"),
161       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
162   EncodeDecode(set);
163   set.types.Clear();
164   // Make sure an IndexSet with only items in IndexSet::namespaces can
165   // be encoded and decoded correctly.
166   set.namespaces.Insert(
167       ConstString("a"),
168       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
169   EncodeDecode(set);
170   set.namespaces.Clear();
171   // Make sure that an IndexSet with item in all NameToDIE maps can be
172   // be encoded and decoded correctly.
173   set.function_basenames.Insert(
174       ConstString("a"),
175       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
176   set.function_fullnames.Insert(
177       ConstString("b"),
178       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
179   set.function_methods.Insert(
180       ConstString("c"),
181       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
182   set.function_selectors.Insert(
183       ConstString("d"),
184       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
185   set.objc_class_selectors.Insert(
186       ConstString("e"),
187       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
188   set.globals.Insert(
189       ConstString("f"),
190       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
191   set.types.Insert(
192       ConstString("g"),
193       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
194   set.namespaces.Insert(
195       ConstString("h"),
196       DIERef(llvm::None, DIERef::Section::DebugInfo, ++die_offset));
197   EncodeDecode(set);
198 }
199