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