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 "../lib/CodeGen/AsmPrinter/DIE.h"
11#include "../lib/CodeGen/AsmPrinter/DIEHash.h"
12#include "llvm/Support/Debug.h"
13#include "llvm/Support/Dwarf.h"
14#include "llvm/Support/Format.h"
15#include "llvm/ADT/STLExtras.h"
16#include "gtest/gtest.h"
17
18using namespace llvm;
19
20namespace {
21TEST(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 {};
31TEST(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 { };
46TEST(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 { }; }
60TEST(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; };
87TEST(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; };
117TEST(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; };
157TEST(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; };
179TEST(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; };
208TEST(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; };
241TEST(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; };
274TEST(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; };
308TEST(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; };
381TEST(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; };
454TEST(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 { }; };
488TEST(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(); };
507TEST(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// };
527TEST(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;
560TEST(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;
605TEST(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