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