1 //===- llvm/unittest/CodeGen/DIEHashTest.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 "../lib/CodeGen/AsmPrinter/DIEHash.h" 10 #include "TestAsmPrinter.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/BinaryFormat/Dwarf.h" 13 #include "llvm/CodeGen/DIE.h" 14 #include "llvm/CodeGen/DwarfStringPoolEntry.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/Support/Format.h" 17 #include "llvm/Support/Host.h" 18 #include "llvm/Testing/Support/Error.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 // Test fixture 26 class DIEHashTest : public testing::Test { 27 public: 28 BumpPtrAllocator Alloc; 29 30 private: 31 StringMap<DwarfStringPoolEntry> Pool; 32 std::unique_ptr<TestAsmPrinter> TestPrinter; 33 34 void setupTestPrinter() { 35 auto ExpectedTestPrinter = TestAsmPrinter::create( 36 sys::getDefaultTargetTriple(), /*DwarfVersion=*/4, dwarf::DWARF32); 37 ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded()); 38 TestPrinter = std::move(ExpectedTestPrinter.get()); 39 } 40 41 public: 42 DIEString getString(StringRef S) { 43 DwarfStringPoolEntry Entry = {nullptr, 1, 1}; 44 return DIEString(DwarfStringPoolEntryRef( 45 *Pool.insert(std::make_pair(S, Entry)).first, Entry.isIndexed())); 46 } 47 48 AsmPrinter *getAsmPrinter() { 49 if (!TestPrinter) 50 setupTestPrinter(); 51 return TestPrinter ? TestPrinter->getAP() : nullptr; 52 } 53 }; 54 55 TEST_F(DIEHashTest, Data1) { 56 DIEHash Hash; 57 DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type); 58 DIEInteger Size(4); 59 Die.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Size); 60 uint64_t MD5Res = Hash.computeTypeSignature(Die); 61 ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res); 62 } 63 64 // struct {}; 65 TEST_F(DIEHashTest, TrivialType) { 66 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 67 DIEInteger One(1); 68 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 69 70 // Line and file number are ignored. 71 Unnamed.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 72 Unnamed.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One); 73 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); 74 75 // The exact same hash GCC produces for this DIE. 76 ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res); 77 } 78 79 // struct foo { }; 80 TEST_F(DIEHashTest, NamedType) { 81 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 82 DIEInteger One(1); 83 DIEString FooStr = getString("foo"); 84 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 85 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 86 87 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 88 89 // The exact same hash GCC produces for this DIE. 90 ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res); 91 } 92 93 // namespace space { struct foo { }; } 94 TEST_F(DIEHashTest, NamespacedType) { 95 DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit); 96 97 auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace); 98 DIEInteger One(1); 99 DIEString SpaceStr = getString("space"); 100 Space->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, SpaceStr); 101 // DW_AT_declaration is ignored. 102 Space->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 103 One); 104 // sibling? 105 106 auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type); 107 DIEString FooStr = getString("foo"); 108 Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 109 Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 110 111 DIE &N = *Foo; 112 Space->addChild(std::move(Foo)); 113 CU.addChild(std::move(Space)); 114 115 uint64_t MD5Res = DIEHash().computeTypeSignature(N); 116 117 // The exact same hash GCC produces for this DIE. 118 ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res); 119 } 120 121 // struct { int member; }; 122 TEST_F(DIEHashTest, TypeWithMember) { 123 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 124 DIEInteger Four(4); 125 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four); 126 127 DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type); 128 DIEString IntStr = getString("int"); 129 Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr); 130 Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four); 131 DIEInteger Five(5); 132 Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five); 133 134 DIEEntry IntRef(Int); 135 136 auto Member = DIE::get(Alloc, dwarf::DW_TAG_member); 137 DIEString MemberStr = getString("member"); 138 Member->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemberStr); 139 DIEInteger Zero(0); 140 Member->addValue(Alloc, dwarf::DW_AT_data_member_location, 141 dwarf::DW_FORM_data1, Zero); 142 Member->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef); 143 144 Unnamed.addChild(std::move(Member)); 145 146 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); 147 148 ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res); 149 } 150 151 // struct foo { int mem1, mem2; }; 152 TEST_F(DIEHashTest, ReusedType) { 153 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 154 DIEInteger Eight(8); 155 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 156 157 DIEInteger Four(4); 158 DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type); 159 DIEString IntStr = getString("int"); 160 Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr); 161 Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four); 162 DIEInteger Five(5); 163 Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five); 164 165 DIEEntry IntRef(Int); 166 167 auto Mem1 = DIE::get(Alloc, dwarf::DW_TAG_member); 168 DIEString Mem1Str = getString("mem1"); 169 Mem1->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem1Str); 170 DIEInteger Zero(0); 171 Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 172 Zero); 173 Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef); 174 175 Unnamed.addChild(std::move(Mem1)); 176 177 auto Mem2 = DIE::get(Alloc, dwarf::DW_TAG_member); 178 DIEString Mem2Str = getString("mem2"); 179 Mem2->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem2Str); 180 Mem2->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 181 Four); 182 Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef); 183 184 Unnamed.addChild(std::move(Mem2)); 185 186 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); 187 188 ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res); 189 } 190 191 // struct foo { static foo f; }; 192 TEST_F(DIEHashTest, RecursiveType) { 193 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 194 DIEInteger One(1); 195 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 196 DIEString FooStr = getString("foo"); 197 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 198 199 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 200 DIEString MemStr = getString("mem"); 201 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 202 DIEEntry FooRef(Foo); 203 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef); 204 // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them. 205 206 Foo.addChild(std::move(Mem)); 207 208 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 209 210 ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res); 211 } 212 213 // struct foo { foo *mem; }; 214 TEST_F(DIEHashTest, Pointer) { 215 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 216 DIEInteger Eight(8); 217 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 218 DIEString FooStr = getString("foo"); 219 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 220 221 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 222 DIEString MemStr = getString("mem"); 223 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 224 DIEInteger Zero(0); 225 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 226 Zero); 227 228 DIE &FooPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type); 229 FooPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 230 DIEEntry FooRef(Foo); 231 FooPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef); 232 233 DIEEntry FooPtrRef(FooPtr); 234 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef); 235 236 Foo.addChild(std::move(Mem)); 237 238 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 239 240 ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res); 241 } 242 243 // struct foo { foo &mem; }; 244 TEST_F(DIEHashTest, Reference) { 245 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 246 DIEInteger Eight(8); 247 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 248 DIEString FooStr = getString("foo"); 249 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 250 251 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 252 DIEString MemStr = getString("mem"); 253 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 254 DIEInteger Zero(0); 255 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 256 Zero); 257 258 DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_reference_type); 259 FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 260 DIEEntry FooEntry(Foo); 261 FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry); 262 263 DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type); 264 DIEEntry FooRefRef(FooRef); 265 FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 266 FooRefRef); 267 268 DIEEntry FooRefConstRef(FooRefConst); 269 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef); 270 271 Foo.addChild(std::move(Mem)); 272 273 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 274 275 ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res); 276 } 277 278 // struct foo { foo &&mem; }; 279 TEST_F(DIEHashTest, RValueReference) { 280 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 281 DIEInteger Eight(8); 282 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 283 DIEString FooStr = getString("foo"); 284 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 285 286 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 287 DIEString MemStr = getString("mem"); 288 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 289 DIEInteger Zero(0); 290 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 291 Zero); 292 293 DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_rvalue_reference_type); 294 FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 295 DIEEntry FooEntry(Foo); 296 FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry); 297 298 DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type); 299 DIEEntry FooRefRef(FooRef); 300 FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 301 FooRefRef); 302 303 DIEEntry FooRefConstRef(FooRefConst); 304 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef); 305 306 Foo.addChild(std::move(Mem)); 307 308 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 309 310 ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res); 311 } 312 313 // struct foo { foo foo::*mem; }; 314 TEST_F(DIEHashTest, PtrToMember) { 315 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 316 DIEInteger Eight(8); 317 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 318 DIEString FooStr = getString("foo"); 319 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 320 321 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 322 DIEString MemStr = getString("mem"); 323 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 324 DIEInteger Zero(0); 325 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 326 Zero); 327 328 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type); 329 DIEEntry FooEntry(Foo); 330 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry); 331 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, 332 FooEntry); 333 334 DIEEntry PtrToFooMemRef(PtrToFooMem); 335 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef); 336 337 Foo.addChild(std::move(Mem)); 338 339 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 340 341 ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res); 342 } 343 344 // Check that the hash for a pointer-to-member matches regardless of whether the 345 // pointed-to type is a declaration or a definition. 346 // 347 // struct bar; // { }; 348 // struct foo { bar foo::*mem; }; 349 TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) { 350 DIEInteger Zero(0); 351 DIEInteger One(1); 352 DIEInteger Eight(8); 353 DIEString FooStr = getString("foo"); 354 DIEString BarStr = getString("bar"); 355 DIEString MemStr = getString("mem"); 356 uint64_t MD5ResDecl; 357 { 358 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 359 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr); 360 Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 361 One); 362 363 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 364 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 365 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 366 367 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 368 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 369 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, 370 dwarf::DW_FORM_data1, Zero); 371 372 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type); 373 DIEEntry BarEntry(Bar); 374 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 375 BarEntry); 376 DIEEntry FooEntry(Foo); 377 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, 378 dwarf::DW_FORM_ref4, FooEntry); 379 380 DIEEntry PtrToFooMemRef(PtrToFooMem); 381 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 382 PtrToFooMemRef); 383 384 Foo.addChild(std::move(Mem)); 385 386 MD5ResDecl = DIEHash().computeTypeSignature(Foo); 387 } 388 uint64_t MD5ResDef; 389 { 390 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 391 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr); 392 Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 393 394 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 395 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 396 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 397 398 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 399 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 400 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, 401 dwarf::DW_FORM_data1, Zero); 402 403 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type); 404 DIEEntry BarEntry(Bar); 405 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 406 BarEntry); 407 DIEEntry FooEntry(Foo); 408 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, 409 dwarf::DW_FORM_ref4, FooEntry); 410 411 DIEEntry PtrToFooMemRef(PtrToFooMem); 412 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 413 PtrToFooMemRef); 414 415 Foo.addChild(std::move(Mem)); 416 417 MD5ResDef = DIEHash().computeTypeSignature(Foo); 418 } 419 ASSERT_EQ(MD5ResDef, MD5ResDecl); 420 } 421 422 // Check that the hash for a pointer-to-member matches regardless of whether the 423 // pointed-to type is a declaration or a definition. 424 // 425 // struct bar; // { }; 426 // struct foo { bar bar::*mem; }; 427 TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) { 428 DIEInteger Zero(0); 429 DIEInteger One(1); 430 DIEInteger Eight(8); 431 DIEString FooStr = getString("foo"); 432 DIEString BarStr = getString("bar"); 433 DIEString MemStr = getString("mem"); 434 uint64_t MD5ResDecl; 435 { 436 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 437 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr); 438 Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 439 One); 440 441 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 442 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 443 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 444 445 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 446 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 447 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, 448 dwarf::DW_FORM_data1, Zero); 449 450 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type); 451 DIEEntry BarEntry(Bar); 452 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 453 BarEntry); 454 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, 455 dwarf::DW_FORM_ref4, BarEntry); 456 457 DIEEntry PtrToFooMemRef(PtrToFooMem); 458 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 459 PtrToFooMemRef); 460 461 Foo.addChild(std::move(Mem)); 462 463 MD5ResDecl = DIEHash().computeTypeSignature(Foo); 464 } 465 uint64_t MD5ResDef; 466 { 467 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 468 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr); 469 Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 470 471 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 472 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 473 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 474 475 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 476 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 477 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, 478 dwarf::DW_FORM_data1, Zero); 479 480 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type); 481 DIEEntry BarEntry(Bar); 482 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 483 BarEntry); 484 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, 485 dwarf::DW_FORM_ref4, BarEntry); 486 487 DIEEntry PtrToFooMemRef(PtrToFooMem); 488 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 489 PtrToFooMemRef); 490 491 Foo.addChild(std::move(Mem)); 492 493 MD5ResDef = DIEHash().computeTypeSignature(Foo); 494 } 495 // FIXME: This seems to be a bug in the DWARF type hashing specification that 496 // only uses the brief name hashing for types referenced via DW_AT_type. In 497 // this case the type is referenced via DW_AT_containing_type and full hashing 498 // causes a hash to differ when the containing type is a declaration in one TU 499 // and a definition in another. 500 ASSERT_NE(MD5ResDef, MD5ResDecl); 501 } 502 503 // struct { } a; 504 // struct foo { decltype(a) mem; }; 505 TEST_F(DIEHashTest, RefUnnamedType) { 506 DIEInteger Zero(0); 507 DIEInteger One(1); 508 DIEInteger Eight(8); 509 DIEString FooStr = getString("foo"); 510 DIEString MemStr = getString("mem"); 511 512 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 513 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 514 515 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 516 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight); 517 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 518 519 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member); 520 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr); 521 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, 522 Zero); 523 524 DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type); 525 UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, 526 Eight); 527 DIEEntry UnnamedRef(Unnamed); 528 UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, 529 UnnamedRef); 530 531 DIEEntry UnnamedPtrRef(UnnamedPtr); 532 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef); 533 534 Foo.addChild(std::move(Mem)); 535 536 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); 537 538 ASSERT_EQ(0x954e026f01c02529ULL, MD5Res); 539 } 540 541 // struct { struct foo { }; }; 542 TEST_F(DIEHashTest, NestedType) { 543 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 544 DIEInteger One(1); 545 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 546 547 auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type); 548 DIEString FooStr = getString("foo"); 549 Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr); 550 Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 551 552 Unnamed.addChild(std::move(Foo)); 553 554 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); 555 556 // The exact same hash GCC produces for this DIE. 557 ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res); 558 } 559 560 // struct { static void func(); }; 561 TEST_F(DIEHashTest, MemberFunc) { 562 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 563 DIEInteger One(1); 564 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 565 566 auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram); 567 DIEString FuncStr = getString("func"); 568 Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr); 569 570 Unnamed.addChild(std::move(Func)); 571 572 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); 573 574 // The exact same hash GCC produces for this DIE. 575 ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res); 576 } 577 578 // struct A { 579 // static void func(); 580 // }; 581 TEST_F(DIEHashTest, MemberFuncFlag) { 582 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 583 DIEInteger One(1); 584 DIEString AStr = getString("A"); 585 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr); 586 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 587 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 588 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One); 589 590 auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram); 591 DIEString FuncStr = getString("func"); 592 DIEString FuncLinkage = getString("_ZN1A4funcEv"); 593 DIEInteger Two(2); 594 Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, 595 One); 596 Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr); 597 Func->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 598 Func->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two); 599 Func->addValue(Alloc, dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, 600 FuncLinkage); 601 Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 602 One); 603 604 A.addChild(std::move(Func)); 605 606 uint64_t MD5Res = DIEHash().computeTypeSignature(A); 607 608 // The exact same hash GCC produces for this DIE. 609 ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res); 610 } 611 612 // Derived from: 613 // struct A { 614 // const static int PI = -3; 615 // }; 616 // A a; 617 TEST_F(DIEHashTest, MemberSdata) { 618 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 619 DIEInteger One(1); 620 DIEString AStr = getString("A"); 621 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr); 622 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 623 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 624 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One); 625 626 DIEInteger Four(4); 627 DIEInteger Five(5); 628 DIEString FStr = getString("int"); 629 DIE &IntTyDIE = *DIE::get(Alloc, dwarf::DW_TAG_base_type); 630 IntTyDIE.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four); 631 IntTyDIE.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five); 632 IntTyDIE.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr); 633 634 DIEEntry IntTy(IntTyDIE); 635 auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type); 636 PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntTy); 637 638 DIEEntry PITy(*PITyDIE); 639 auto PI = DIE::get(Alloc, dwarf::DW_TAG_member); 640 DIEString PIStr = getString("PI"); 641 DIEInteger Two(2); 642 DIEInteger NegThree(-3); 643 PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr); 644 PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 645 PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two); 646 PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy); 647 PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One); 648 PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 649 One); 650 PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree); 651 652 A.addChild(std::move(PI)); 653 654 uint64_t MD5Res = DIEHash().computeTypeSignature(A); 655 ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res); 656 } 657 658 // Derived from: 659 // struct A { 660 // const static float PI = 3.14; 661 // }; 662 // A a; 663 TEST_F(DIEHashTest, MemberBlock) { 664 if (!this->getAsmPrinter()) 665 // TODO: Use GTEST_SKIP() when GTest is updated to version 1.10.0 666 return; 667 668 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type); 669 DIEInteger One(1); 670 DIEString AStr = getString("A"); 671 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr); 672 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One); 673 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 674 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One); 675 676 DIEInteger Four(4); 677 DIEString FStr = getString("float"); 678 auto FloatTyDIE = DIE::get(Alloc, dwarf::DW_TAG_base_type); 679 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, 680 Four); 681 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, 682 Four); 683 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr); 684 DIEEntry FloatTy(*FloatTyDIE); 685 auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type); 686 PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FloatTy); 687 688 DIEEntry PITy(*PITyDIE); 689 auto PI = DIE::get(Alloc, dwarf::DW_TAG_member); 690 DIEString PIStr = getString("PI"); 691 DIEInteger Two(2); 692 PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr); 693 PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One); 694 PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two); 695 PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy); 696 PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One); 697 PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 698 One); 699 700 DIEBlock PIBlock; 701 DIEInteger Blk1(0xc3); 702 DIEInteger Blk2(0xf5); 703 DIEInteger Blk3(0x48); 704 DIEInteger Blk4(0x40); 705 706 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk1); 707 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk2); 708 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk3); 709 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk4); 710 711 PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, 712 &PIBlock); 713 714 A.addChild(std::move(PI)); 715 716 uint64_t MD5Res = DIEHash(this->getAsmPrinter()).computeTypeSignature(A); 717 ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res); 718 } 719 } 720