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_EQ(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 map.Finalize(); 87 // Make sure a valid NameToDIE map encodes and decodes correctly. 88 EncodeDecode(map); 89 } 90 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 105 static void EncodeDecode(const ManualDWARFIndex::IndexSet &object) { 106 EncodeDecode(object, eByteOrderLittle); 107 EncodeDecode(object, eByteOrderBig); 108 } 109 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 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 216 static void EncodeDecode(const CacheSignature &object, bool encode_result) { 217 EncodeDecode(object, eByteOrderLittle, encode_result); 218 EncodeDecode(object, eByteOrderBig, encode_result); 219 } 220 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