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