xref: /llvm-project/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp (revision 5153a90453e692b834e38eec247a0c88a0678bfa)
1 //===-- DWARFDIETest.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 "Plugins/SymbolFile/DWARF/DWARFDIE.h"
10 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
12 #include "TestingSupport/Symbol/YAMLModuleTester.h"
13 #include "lldb/Core/dwarf.h"
14 #include "lldb/Symbol/Type.h"
15 #include "lldb/lldb-private-enumerations.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::plugin::dwarf;
23 using namespace lldb_private::dwarf;
24 
25 TEST(DWARFDIETest, ChildIteration) {
26   // Tests DWARFDIE::child_iterator.
27 
28   const char *yamldata = R"(
29 --- !ELF
30 FileHeader:
31   Class:   ELFCLASS64
32   Data:    ELFDATA2LSB
33   Type:    ET_EXEC
34   Machine: EM_386
35 DWARF:
36   debug_abbrev:
37     - Table:
38         - Code:            0x00000001
39           Tag:             DW_TAG_compile_unit
40           Children:        DW_CHILDREN_yes
41           Attributes:
42             - Attribute:       DW_AT_language
43               Form:            DW_FORM_data2
44         - Code:            0x00000002
45           Tag:             DW_TAG_base_type
46           Children:        DW_CHILDREN_no
47           Attributes:
48             - Attribute:       DW_AT_encoding
49               Form:            DW_FORM_data1
50             - Attribute:       DW_AT_byte_size
51               Form:            DW_FORM_data1
52   debug_info:
53     - Version:         4
54       AddrSize:        8
55       Entries:
56         - AbbrCode:        0x00000001
57           Values:
58             - Value:           0x000000000000000C
59         - AbbrCode:        0x00000002
60           Values:
61             - Value:           0x0000000000000007 # DW_ATE_unsigned
62             - Value:           0x0000000000000004
63         - AbbrCode:        0x00000002
64           Values:
65             - Value:           0x0000000000000007 # DW_ATE_unsigned
66             - Value:           0x0000000000000008
67         - AbbrCode:        0x00000002
68           Values:
69             - Value:           0x0000000000000005 # DW_ATE_signed
70             - Value:           0x0000000000000008
71         - AbbrCode:        0x00000000
72 )";
73 
74   YAMLModuleTester t(yamldata);
75   ASSERT_TRUE((bool)t.GetDwarfUnit());
76 
77   DWARFUnit *unit = t.GetDwarfUnit();
78   const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE();
79 
80   // Create a DWARFDIE that has three DW_TAG_base_type children.
81   DWARFDIE top_die(unit, die_first);
82 
83   // Create the iterator range that has the three tags as elements.
84   llvm::iterator_range<DWARFDIE::child_iterator> children = top_die.children();
85 
86   // Compare begin() to the first child DIE.
87   DWARFDIE::child_iterator child_iter = children.begin();
88   ASSERT_NE(child_iter, children.end());
89   const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild();
90   EXPECT_EQ((*child_iter).GetDIE(), die_child0);
91 
92   // Step to the second child DIE.
93   ++child_iter;
94   ASSERT_NE(child_iter, children.end());
95   const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling();
96   EXPECT_EQ((*child_iter).GetDIE(), die_child1);
97 
98   // Step to the third child DIE.
99   ++child_iter;
100   ASSERT_NE(child_iter, children.end());
101   const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling();
102   EXPECT_EQ((*child_iter).GetDIE(), die_child2);
103 
104   // Step to the end of the range.
105   ++child_iter;
106   EXPECT_EQ(child_iter, children.end());
107 
108   // Take one of the DW_TAG_base_type DIEs (which has no children) and make
109   // sure the children range is now empty.
110   DWARFDIE no_children_die(unit, die_child0);
111   EXPECT_TRUE(no_children_die.children().empty());
112 }
113 
114 TEST(DWARFDIETest, PeekName) {
115   const char *yamldata = R"(
116 --- !ELF
117 FileHeader:
118   Class:   ELFCLASS64
119   Data:    ELFDATA2LSB
120   Type:    ET_EXEC
121   Machine: EM_386
122 DWARF:
123   debug_str:
124     - 'NameType1'
125     - 'NameType2'
126   debug_abbrev:
127     - Table:
128         - Code:            0x00000001
129           Tag:             DW_TAG_compile_unit
130           Children:        DW_CHILDREN_yes
131           Attributes:
132             - Attribute:       DW_AT_language
133               Form:            DW_FORM_data2
134         - Code:            0x00000002
135           Tag:             DW_TAG_base_type
136           Children:        DW_CHILDREN_no
137           Attributes:
138             - Attribute:       DW_AT_name
139               Form:            DW_FORM_strp
140         - Code:            0x00000003
141           Tag:             DW_TAG_base_type
142           Children:        DW_CHILDREN_no
143           Attributes:
144             - Attribute:       DW_AT_abstract_origin
145               Form:            DW_FORM_ref1
146         - Code:            0x00000004
147           Tag:             DW_TAG_base_type
148           Children:        DW_CHILDREN_no
149           Attributes:
150             - Attribute:       DW_AT_specification
151               Form:            DW_FORM_ref1
152   debug_info:
153     - Version:         4
154       AddrSize:        8
155       Entries:
156         - AbbrCode:        0x00000001
157           Values:
158             - Value:           0x000000000000000C
159         - AbbrCode:        0x00000002
160           Values:
161             - Value:           0x0000000000000000 # Name = NameType1
162         - AbbrCode:        0x00000002
163           Values:
164             - Value:           0x000000000000000a # Name = NameType2
165         - AbbrCode:        0x00000003
166           Values:
167             - Value:           0x000000000000000e # Ref abstract origin to NameType1 DIE.
168         - AbbrCode:        0x00000004
169           Values:
170             - Value:           0x0000000000000013 # Ref specification to NameType2 DIE.
171         - AbbrCode:        0x00000000
172 )";
173 
174   YAMLModuleTester t(yamldata);
175   auto *symbol_file =
176       llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
177   DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
178 
179   dw_offset_t first_die_offset = 11;
180   EXPECT_EQ(unit->PeekDIEName(first_die_offset), "");
181 
182   dw_offset_t second_die_offset = 14;
183   EXPECT_EQ(unit->PeekDIEName(second_die_offset), "NameType1");
184 
185   dw_offset_t third_die_offset = 19;
186   EXPECT_EQ(unit->PeekDIEName(third_die_offset), "NameType2");
187 
188   dw_offset_t fourth_die_offset = 24;
189   EXPECT_EQ(unit->PeekDIEName(fourth_die_offset), "NameType1");
190 
191   dw_offset_t fifth_die_offset = 26;
192   EXPECT_EQ(unit->PeekDIEName(fifth_die_offset), "NameType2");
193 }
194 
195 TEST(DWARFDIETest, GetContext) {
196   const char *yamldata = R"(
197 --- !ELF
198 FileHeader:
199   Class:   ELFCLASS64
200   Data:    ELFDATA2LSB
201   Type:    ET_EXEC
202   Machine: EM_386
203 DWARF:
204   debug_abbrev:
205     - ID:              0
206       Table:
207         - Code:            0x1
208           Tag:             DW_TAG_compile_unit
209           Children:        DW_CHILDREN_yes
210           Attributes:
211             - Attribute:       DW_AT_language
212               Form:            DW_FORM_data2
213         - Code:            0x2
214           Tag:             DW_TAG_namespace
215           Children:        DW_CHILDREN_yes
216           Attributes:
217             - Attribute:       DW_AT_name
218               Form:            DW_FORM_string
219         - Code:            0x3
220           Tag:             DW_TAG_structure_type
221           Children:        DW_CHILDREN_no
222           Attributes:
223             - Attribute:       DW_AT_name
224               Form:            DW_FORM_string
225         - Code:            0x4
226           Tag:             DW_TAG_namespace
227           Children:        DW_CHILDREN_yes
228   debug_info:
229     - Version:         4
230       AddrSize:        8
231       Entries:
232         - AbbrCode:        0x1
233           Values:
234             - Value:           0x000000000000000C
235         - AbbrCode:        0x2
236           Values:
237             - CStr:            NAMESPACE
238         - AbbrCode:        0x3
239           Values:
240             - CStr:            STRUCT
241         - AbbrCode:        0x4
242         - AbbrCode:        0x3
243           Values:
244             - CStr:            STRUCT
245         - AbbrCode:        0x0
246         - AbbrCode:        0x0
247         - AbbrCode:        0x0
248 )";
249 
250   YAMLModuleTester t(yamldata);
251   auto *symbol_file =
252       llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
253   DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
254   ASSERT_TRUE(unit);
255 
256   auto make_namespace = [](const char *name) {
257     return CompilerContext(CompilerContextKind::Namespace, ConstString(name));
258   };
259   auto make_struct = [](const char *name) {
260     return CompilerContext(CompilerContextKind::ClassOrStruct,
261                            ConstString(name));
262   };
263   DWARFDIE struct_die = unit->DIE().GetFirstChild().GetFirstChild();
264   ASSERT_TRUE(struct_die);
265   DWARFDIE anon_struct_die = struct_die.GetSibling().GetFirstChild();
266   ASSERT_TRUE(anon_struct_die);
267   EXPECT_THAT(
268       struct_die.GetDeclContext(),
269       testing::ElementsAre(make_namespace("NAMESPACE"), make_struct("STRUCT")));
270   EXPECT_THAT(
271       struct_die.GetTypeLookupContext(),
272       testing::ElementsAre(make_namespace("NAMESPACE"), make_struct("STRUCT")));
273   EXPECT_THAT(struct_die.GetDWARFDeclContext(),
274               DWARFDeclContext({{DW_TAG_structure_type, "STRUCT"},
275                                 {DW_TAG_namespace, "NAMESPACE"}}));
276   EXPECT_THAT(anon_struct_die.GetDeclContext(),
277               testing::ElementsAre(make_namespace("NAMESPACE"),
278                                    make_namespace(nullptr),
279                                    make_struct("STRUCT")));
280   EXPECT_THAT(anon_struct_die.GetTypeLookupContext(),
281               testing::ElementsAre(make_namespace("NAMESPACE"),
282                                    make_namespace(nullptr),
283                                    make_struct("STRUCT")));
284   EXPECT_THAT(anon_struct_die.GetDWARFDeclContext(),
285               DWARFDeclContext({{DW_TAG_structure_type, "STRUCT"},
286                                 {DW_TAG_namespace, nullptr},
287                                 {DW_TAG_namespace, "NAMESPACE"}}));
288 }
289 
290 TEST(DWARFDIETest, GetContextInFunction) {
291   // Make sure we get the right context fo each "struct_t" type. The first
292   // should be "a::struct_t" and the one defined in the "foo" function should be
293   // "struct_t". Previous DWARFDIE::GetTypeLookupContext() function calls would
294   // have the "struct_t" in "foo" be "a::struct_t" because it would traverse the
295   // entire die parent tree and ignore DW_TAG_subprogram and keep traversing the
296   // parents.
297   //
298   // 0x0000000b: DW_TAG_compile_unit
299   // 0x0000000c:   DW_TAG_namespace
300   //                 DW_AT_name("a")
301   // 0x0000000f:     DW_TAG_structure_type
302   //                   DW_AT_name("struct_t")
303   // 0x00000019:     DW_TAG_subprogram
304   //                   DW_AT_name("foo")
305   // 0x0000001e:       DW_TAG_structure_type
306   //                     DW_AT_name("struct_t")
307   // 0x00000028:       NULL
308   // 0x00000029:     NULL
309   // 0x0000002a:   NULL
310   const char *yamldata = R"(
311 --- !ELF
312 FileHeader:
313   Class:   ELFCLASS64
314   Data:    ELFDATA2LSB
315   Type:    ET_EXEC
316   Machine: EM_386
317 DWARF:
318   debug_str:
319     - ''
320   debug_abbrev:
321     - ID:              0
322       Table:
323         - Code:            0x1
324           Tag:             DW_TAG_compile_unit
325           Children:        DW_CHILDREN_yes
326         - Code:            0x2
327           Tag:             DW_TAG_namespace
328           Children:        DW_CHILDREN_yes
329           Attributes:
330             - Attribute:       DW_AT_name
331               Form:            DW_FORM_string
332         - Code:            0x3
333           Tag:             DW_TAG_structure_type
334           Children:        DW_CHILDREN_no
335           Attributes:
336             - Attribute:       DW_AT_name
337               Form:            DW_FORM_string
338         - Code:            0x4
339           Tag:             DW_TAG_subprogram
340           Children:        DW_CHILDREN_yes
341           Attributes:
342             - Attribute:       DW_AT_name
343               Form:            DW_FORM_string
344   debug_info:
345     - Length:          0x27
346       Version:         4
347       AbbrevTableID:   0
348       AbbrOffset:      0x0
349       AddrSize:        8
350       Entries:
351         - AbbrCode:        0x1
352         - AbbrCode:        0x2
353           Values:
354             - Value:           0xDEADBEEFDEADBEEF
355               CStr:            a
356         - AbbrCode:        0x3
357           Values:
358             - Value:           0xDEADBEEFDEADBEEF
359               CStr:            struct_t
360         - AbbrCode:        0x4
361           Values:
362             - Value:           0xDEADBEEFDEADBEEF
363               CStr:            foo
364         - AbbrCode:        0x3
365           Values:
366             - Value:           0xDEADBEEFDEADBEEF
367               CStr:            struct_t
368         - AbbrCode:        0x0
369         - AbbrCode:        0x0
370         - AbbrCode:        0x0)";
371 
372   YAMLModuleTester t(yamldata);
373   auto *symbol_file =
374       llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
375   DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
376   ASSERT_TRUE(unit);
377 
378   auto make_namespace = [](llvm::StringRef name) {
379     return CompilerContext(CompilerContextKind::Namespace, ConstString(name));
380   };
381   auto make_struct = [](llvm::StringRef name) {
382     return CompilerContext(CompilerContextKind::ClassOrStruct,
383                            ConstString(name));
384   };
385   // Grab the "a::struct_t" type from the "a" namespace
386   DWARFDIE a_struct_die = unit->DIE().GetFirstChild().GetFirstChild();
387   ASSERT_TRUE(a_struct_die);
388   EXPECT_THAT(
389       a_struct_die.GetDeclContext(),
390       testing::ElementsAre(make_namespace("a"), make_struct("struct_t")));
391   // Grab the "struct_t" defined in the "foo" function.
392   DWARFDIE foo_struct_die =
393       unit->DIE().GetFirstChild().GetFirstChild().GetSibling().GetFirstChild();
394   EXPECT_THAT(foo_struct_die.GetTypeLookupContext(),
395               testing::ElementsAre(make_struct("struct_t")));
396 }
397 
398 struct GetAttributesTestFixture : public testing::TestWithParam<dw_attr_t> {};
399 
400 TEST_P(GetAttributesTestFixture, TestGetAttributes_IterationOrder) {
401   // Tests that we accumulate all current DIE's attributes first
402   // before checking the attributes of the specification.
403 
404   const char *yamldata = R"(
405 --- !ELF
406 FileHeader:
407   Class:   ELFCLASS64
408   Data:    ELFDATA2LSB
409   Type:    ET_EXEC
410   Machine: EM_AARCH64
411 DWARF:
412   debug_str:
413     - func
414   debug_abbrev:
415     - ID:              0
416       Table:
417         - Code:            0x1
418           Tag:             DW_TAG_compile_unit
419           Children:        DW_CHILDREN_yes
420           Attributes:
421             - Attribute:       DW_AT_language
422               Form:            DW_FORM_data2
423         - Code:            0x2
424           Tag:             DW_TAG_subprogram
425           Children:        DW_CHILDREN_no
426           Attributes:
427             - Attribute:       DW_AT_high_pc
428               Form:            DW_FORM_data4
429             - Attribute:       DW_AT_name
430               Form:            DW_FORM_strp
431             - Attribute:       DW_AT_declaration
432               Form:            DW_FORM_flag_present
433             - Attribute:       DW_AT_external
434               Form:            DW_FORM_flag_present
435             - Attribute:       DW_AT_low_pc
436               Form:            DW_FORM_data4
437         - Code:            0x3
438           Tag:             DW_TAG_subprogram
439           Children:        DW_CHILDREN_no
440           Attributes:
441             - Attribute:       DW_AT_high_pc
442               Form:            DW_FORM_data4
443             - Attribute:       {0}
444               Form:            DW_FORM_ref4
445             - Attribute:       DW_AT_low_pc
446               Form:            DW_FORM_data4
447   debug_info:
448      - Version:         5
449        UnitType:        DW_UT_compile
450        AddrSize:        8
451        Entries:
452 
453 # DW_TAG_compile_unit
454 #   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
455 
456         - AbbrCode:        0x1
457           Values:
458             - Value:           0x04
459 
460 #     DW_TAG_subprogram
461 #       DW_AT_high_pc [DW_FORM_data4]
462 #       DW_AT_name [DW_FORM_strp] ("func")
463 #       DW_AT_low_pc [DW_FORM_data4]
464         - AbbrCode:        0x2
465           Values:
466             - Value:           0xdeadbeef
467             - Value:           0x0
468             - Value:           0x1
469             - Value:           0x1
470             - Value:           0xdeadbeef
471 
472 #     DW_TAG_subprogram
473 #       DW_AT_high_pc [DW_FORM_data4]
474 #       DW_AT_specification [DW_FORM_ref4] ("func")
475 #       DW_AT_low_pc [DW_FORM_data4]
476         - AbbrCode:        0x3
477           Values:
478             - Value:           0xf00dcafe
479             - Value:           0xf
480             - Value:           0xf00dcafe
481 
482         - AbbrCode: 0x0
483 ...
484 )";
485   YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str());
486 
487   DWARFUnit *unit = t.GetDwarfUnit();
488   ASSERT_NE(unit, nullptr);
489   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
490   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
491   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
492   DWARFDIE cu_die(unit, cu_entry);
493 
494   auto declaration = cu_die.GetFirstChild();
495   ASSERT_TRUE(declaration.IsValid());
496   ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
497 
498   auto definition = declaration.GetSibling();
499   ASSERT_TRUE(definition.IsValid());
500   ASSERT_EQ(definition.Tag(), DW_TAG_subprogram);
501   ASSERT_FALSE(definition.GetAttributeValueAsOptionalUnsigned(DW_AT_external));
502 
503   auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes);
504   EXPECT_EQ(attrs.Size(), 7U);
505 
506   // Check that the attributes on the definition (that are also present
507   // on the declaration) take precedence.
508   for (auto attr : {DW_AT_low_pc, DW_AT_high_pc}) {
509     auto idx = attrs.FindAttributeIndex(attr);
510     EXPECT_NE(idx, UINT32_MAX);
511 
512     DWARFFormValue form_value;
513     auto success = attrs.ExtractFormValueAtIndex(idx, form_value);
514     EXPECT_TRUE(success);
515 
516     EXPECT_EQ(form_value.Unsigned(), 0xf00dcafe);
517   }
518 }
519 
520 TEST_P(GetAttributesTestFixture, TestGetAttributes_Cycle) {
521   // Tests that GetAttributes can deal with cycles in
522   // specifications/abstract origins.
523   //
524   // Contrived example:
525   //
526   // func1 -> func3
527   //   ^       |
528   //   |       v
529   //   +------func2
530 
531   const char *yamldata = R"(
532 --- !ELF
533 FileHeader:
534   Class:   ELFCLASS64
535   Data:    ELFDATA2LSB
536   Type:    ET_EXEC
537   Machine: EM_AARCH64
538 DWARF:
539   debug_abbrev:
540     - ID:              0
541       Table:
542         - Code:            0x1
543           Tag:             DW_TAG_compile_unit
544           Children:        DW_CHILDREN_yes
545           Attributes:
546             - Attribute:       DW_AT_language
547               Form:            DW_FORM_data2
548         - Code:            0x2
549           Tag:             DW_TAG_subprogram
550           Children:        DW_CHILDREN_no
551           Attributes:
552             - Attribute:       {0}
553               Form:            DW_FORM_ref4
554   debug_info:
555      - Version:         5
556        UnitType:        DW_UT_compile
557        AddrSize:        8
558        Entries:
559 
560         - AbbrCode:        0x1
561           Values:
562             - Value:           0x04
563 
564         - AbbrCode:        0x2
565           Values:
566             - Value:           0x19
567 
568         - AbbrCode:        0x2
569           Values:
570             - Value:           0xf
571 
572         - AbbrCode:        0x2
573           Values:
574             - Value:           0x14
575 
576         - AbbrCode: 0x0
577 ...
578 )";
579   YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str());
580 
581   DWARFUnit *unit = t.GetDwarfUnit();
582   ASSERT_NE(unit, nullptr);
583   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
584   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
585   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
586   DWARFDIE cu_die(unit, cu_entry);
587 
588   auto func1 = cu_die.GetFirstChild();
589   ASSERT_TRUE(func1.IsValid());
590   ASSERT_EQ(func1.Tag(), DW_TAG_subprogram);
591 
592   auto func2 = func1.GetSibling();
593   ASSERT_TRUE(func2.IsValid());
594   ASSERT_EQ(func2.Tag(), DW_TAG_subprogram);
595 
596   auto func3 = func2.GetSibling();
597   ASSERT_TRUE(func3.IsValid());
598   ASSERT_EQ(func3.Tag(), DW_TAG_subprogram);
599 
600   auto attrs = func1.GetAttributes(DWARFDebugInfoEntry::Recurse::yes);
601   EXPECT_EQ(attrs.Size(), 3U);
602 
603   // Confirm that the specifications do form a cycle.
604   {
605     DWARFFormValue form_value;
606     auto success = attrs.ExtractFormValueAtIndex(0, form_value);
607     ASSERT_TRUE(success);
608 
609     EXPECT_EQ(form_value.Reference(), func3);
610   }
611 
612   {
613     DWARFFormValue form_value;
614     auto success = attrs.ExtractFormValueAtIndex(1, form_value);
615     ASSERT_TRUE(success);
616 
617     EXPECT_EQ(form_value.Reference(), func2);
618   }
619 
620   {
621     DWARFFormValue form_value;
622     auto success = attrs.ExtractFormValueAtIndex(2, form_value);
623     ASSERT_TRUE(success);
624 
625     EXPECT_EQ(form_value.Reference(), func1);
626   }
627 }
628 
629 TEST_P(GetAttributesTestFixture,
630        TestGetAttributes_SkipNonApplicableAttributes) {
631   // Tests that GetAttributes will omit attributes found through
632   // specifications/abstract origins which are not applicable.
633 
634   const char *yamldata = R"(
635 --- !ELF
636 FileHeader:
637   Class:   ELFCLASS64
638   Data:    ELFDATA2LSB
639   Type:    ET_EXEC
640   Machine: EM_AARCH64
641 DWARF:
642   debug_str:
643     - func
644   debug_abbrev:
645     - ID:              0
646       Table:
647         - Code:            0x1
648           Tag:             DW_TAG_compile_unit
649           Children:        DW_CHILDREN_yes
650           Attributes:
651             - Attribute:       DW_AT_language
652               Form:            DW_FORM_data2
653         - Code:            0x2
654           Tag:             DW_TAG_subprogram
655           Children:        DW_CHILDREN_no
656           Attributes:
657             - Attribute:       DW_AT_declaration
658               Form:            DW_FORM_flag_present
659             - Attribute:       DW_AT_name
660               Form:            DW_FORM_strp
661             - Attribute:       DW_AT_sibling
662               Form:            DW_FORM_ref4
663         - Code:            0x3
664           Tag:             DW_TAG_subprogram
665           Children:        DW_CHILDREN_no
666           Attributes:
667             - Attribute:       DW_AT_declaration
668               Form:            DW_FORM_flag_present
669             - Attribute:       {0}
670               Form:            DW_FORM_ref4
671             - Attribute:       DW_AT_sibling
672               Form:            DW_FORM_ref4
673   debug_info:
674      - Version:         5
675        UnitType:        DW_UT_compile
676        AddrSize:        8
677        Entries:
678 
679 # DW_TAG_compile_unit
680 #   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
681 
682         - AbbrCode:        0x1
683           Values:
684             - Value:           0x04
685 
686 #     DW_TAG_subprogram
687 #       DW_AT_declaration
688 #       DW_AT_name [DW_FORM_strp] ("func")
689 #       DW_AT_sibling
690         - AbbrCode:        0x2
691           Values:
692             - Value:           0x1
693             - Value:           0x0
694             - Value:           0x18
695 
696 #     DW_TAG_subprogram
697 #       DW_AT_declaration
698 #       DW_AT_specification [DW_FORM_ref4] ("func")
699 #       DW_AT_sibling
700         - AbbrCode:        0x3
701           Values:
702             - Value:           0x1
703             - Value:           0xf
704             - Value:           0xdeadbeef
705 
706         - AbbrCode: 0x0
707 ...
708 )";
709   YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str());
710 
711   DWARFUnit *unit = t.GetDwarfUnit();
712   ASSERT_NE(unit, nullptr);
713   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
714   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
715   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
716   DWARFDIE cu_die(unit, cu_entry);
717 
718   auto declaration = cu_die.GetFirstChild();
719   ASSERT_TRUE(declaration.IsValid());
720   ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
721 
722   auto definition = declaration.GetSibling();
723   ASSERT_TRUE(definition.IsValid());
724   ASSERT_EQ(definition.Tag(), DW_TAG_subprogram);
725 
726   auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes);
727   EXPECT_EQ(attrs.Size(), 4U);
728   EXPECT_NE(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX);
729   EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX);
730 
731   auto sibling_idx = attrs.FindAttributeIndex(DW_AT_sibling);
732   EXPECT_NE(sibling_idx, UINT32_MAX);
733 
734   DWARFFormValue form_value;
735   auto success = attrs.ExtractFormValueAtIndex(sibling_idx, form_value);
736   ASSERT_TRUE(success);
737 
738   EXPECT_EQ(form_value.Unsigned(), 0xdeadbeef);
739 }
740 
741 TEST_P(GetAttributesTestFixture, TestGetAttributes_NoRecurse) {
742   // Tests that GetAttributes will not recurse if Recurse::No is passed to it.
743 
744   const char *yamldata = R"(
745 --- !ELF
746 FileHeader:
747   Class:   ELFCLASS64
748   Data:    ELFDATA2LSB
749   Type:    ET_EXEC
750   Machine: EM_AARCH64
751 DWARF:
752   debug_str:
753     - func
754   debug_abbrev:
755     - ID:              0
756       Table:
757         - Code:            0x1
758           Tag:             DW_TAG_compile_unit
759           Children:        DW_CHILDREN_yes
760           Attributes:
761             - Attribute:       DW_AT_language
762               Form:            DW_FORM_data2
763         - Code:            0x2
764           Tag:             DW_TAG_subprogram
765           Children:        DW_CHILDREN_no
766           Attributes:
767             - Attribute:       DW_AT_name
768               Form:            DW_FORM_strp
769         - Code:            0x3
770           Tag:             DW_TAG_subprogram
771           Children:        DW_CHILDREN_no
772           Attributes:
773             - Attribute:       DW_AT_low_pc
774               Form:            DW_FORM_data4
775             - Attribute:       {0}
776               Form:            DW_FORM_ref4
777   debug_info:
778      - Version:         5
779        UnitType:        DW_UT_compile
780        AddrSize:        8
781        Entries:
782 
783 # DW_TAG_compile_unit
784 #   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
785 
786         - AbbrCode:        0x1
787           Values:
788             - Value:           0x04
789 
790 #     DW_TAG_subprogram
791 #       DW_AT_name [DW_FORM_strp] ("func")
792         - AbbrCode:        0x2
793           Values:
794             - Value:           0x0
795 
796 #     DW_TAG_subprogram
797 #       DW_AT_low_pc [DW_FORM_data4]
798 #       DW_AT_specification [DW_FORM_ref4]
799         - AbbrCode:        0x3
800           Values:
801             - Value:           0xdeadbeef
802             - Value:           0xf
803 
804         - AbbrCode: 0x0
805 ...
806 )";
807   YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str());
808 
809   DWARFUnit *unit = t.GetDwarfUnit();
810   ASSERT_NE(unit, nullptr);
811   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
812   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
813   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
814   DWARFDIE cu_die(unit, cu_entry);
815 
816   auto declaration = cu_die.GetFirstChild();
817   ASSERT_TRUE(declaration.IsValid());
818   ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
819 
820   auto definition = declaration.GetSibling();
821   ASSERT_TRUE(definition.IsValid());
822   ASSERT_EQ(definition.Tag(), DW_TAG_subprogram);
823 
824   auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::no);
825   EXPECT_EQ(attrs.Size(), 2U);
826   EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX);
827   EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX);
828   EXPECT_NE(attrs.FindAttributeIndex(DW_AT_low_pc), UINT32_MAX);
829 }
830 
831 TEST_P(GetAttributesTestFixture, TestGetAttributes_InvalidSpec) {
832   // Test that GetAttributes doesn't try following invalid
833   // specifications (but still add it to the list of attributes).
834 
835   const char *yamldata = R"(
836 --- !ELF
837 FileHeader:
838   Class:   ELFCLASS64
839   Data:    ELFDATA2LSB
840   Type:    ET_EXEC
841   Machine: EM_AARCH64
842 DWARF:
843   debug_str:
844     - func
845   debug_abbrev:
846     - ID:              0
847       Table:
848         - Code:            0x1
849           Tag:             DW_TAG_compile_unit
850           Children:        DW_CHILDREN_yes
851           Attributes:
852             - Attribute:       DW_AT_language
853               Form:            DW_FORM_data2
854         - Code:            0x2
855           Tag:             DW_TAG_subprogram
856           Children:        DW_CHILDREN_no
857           Attributes:
858             - Attribute:       DW_AT_name
859               Form:            DW_FORM_strp
860         - Code:            0x3
861           Tag:             DW_TAG_subprogram
862           Children:        DW_CHILDREN_no
863           Attributes:
864             - Attribute:       {0}
865               Form:            DW_FORM_ref4
866   debug_info:
867      - Version:         5
868        UnitType:        DW_UT_compile
869        AddrSize:        8
870        Entries:
871 
872 # DW_TAG_compile_unit
873 #   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
874 
875         - AbbrCode:        0x1
876           Values:
877             - Value:           0x04
878 
879 #     DW_TAG_subprogram
880 #       DW_AT_name [DW_FORM_strp] ("func")
881         - AbbrCode:        0x2
882           Values:
883             - Value:           0x0
884 
885 #     DW_TAG_subprogram
886 #       DW_AT_specification [DW_FORM_ref4]
887         - AbbrCode:        0x3
888           Values:
889             - Value:           0xdeadbeef
890 
891         - AbbrCode: 0x0
892 ...
893 )";
894   YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str());
895 
896   DWARFUnit *unit = t.GetDwarfUnit();
897   ASSERT_NE(unit, nullptr);
898   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
899   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
900   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
901   DWARFDIE cu_die(unit, cu_entry);
902 
903   auto declaration = cu_die.GetFirstChild();
904   ASSERT_TRUE(declaration.IsValid());
905   ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
906 
907   auto definition = declaration.GetSibling();
908   ASSERT_TRUE(definition.IsValid());
909   ASSERT_EQ(definition.Tag(), DW_TAG_subprogram);
910 
911   auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes);
912   EXPECT_EQ(attrs.Size(), 1U);
913   EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX);
914   EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX);
915 }
916 
917 TEST(DWARFDIETest, TestGetAttributes_Worklist) {
918   // Test that GetAttributes will follow both the abstract origin
919   // and specification on a single DIE correctly (omitting non-applicable
920   // attributes in the process).
921 
922   // Contrived example where
923   // f1---> f2 --> f4
924   //    `-> f3 `-> f5
925   //
926   const char *yamldata = R"(
927 --- !ELF
928 FileHeader:
929   Class:   ELFCLASS64
930   Data:    ELFDATA2LSB
931   Type:    ET_EXEC
932   Machine: EM_AARCH64
933 DWARF:
934   debug_str:
935     - foo
936     - bar
937   debug_abbrev:
938     - ID:              0
939       Table:
940         - Code:            0x1
941           Tag:             DW_TAG_compile_unit
942           Children:        DW_CHILDREN_yes
943           Attributes:
944             - Attribute:       DW_AT_language
945               Form:            DW_FORM_data2
946         - Code:            0x2
947           Tag:             DW_TAG_subprogram
948           Children:        DW_CHILDREN_no
949           Attributes:
950             - Attribute:       DW_AT_specification
951               Form:            DW_FORM_ref4
952             - Attribute:       DW_AT_abstract_origin
953               Form:            DW_FORM_ref4
954         - Code:            0x3
955           Tag:             DW_TAG_subprogram
956           Children:        DW_CHILDREN_no
957           Attributes:
958             - Attribute:       DW_AT_declaration
959               Form:            DW_FORM_flag_present
960             - Attribute:       DW_AT_artificial
961               Form:            DW_FORM_flag_present
962 
963   debug_info:
964      - Version:         5
965        UnitType:        DW_UT_compile
966        AddrSize:        8
967        Entries:
968 
969         - AbbrCode:        0x1
970           Values:
971             - Value:           0x04
972 
973 #     DW_TAG_subprogram ("f1")
974 #       DW_AT_specification [DW_FORM_ref4] ("f2")
975 #       DW_AT_abstract_origin [DW_FORM_ref4] ("f3")
976         - AbbrCode:        0x2
977           Values:
978             - Value:           0x18
979             - Value:           0x21
980 
981 #     DW_TAG_subprogram ("f2")
982 #       DW_AT_specification [DW_FORM_ref4] ("f4")
983 #       DW_AT_abstract_origin [DW_FORM_ref4] ("f5")
984         - AbbrCode:        0x2
985           Values:
986             - Value:           0x22
987             - Value:           0x23
988 
989 #     DW_TAG_subprogram ("f3")
990 #       DW_AT_declaration [DW_FORM_flag_present]
991 #       DW_AT_artificial [DW_FORM_flag_present]
992         - AbbrCode:        0x3
993           Values:
994             - Value:           0x1
995             - Value:           0x1
996 
997 #     DW_TAG_subprogram ("f4")
998 #       DW_AT_declaration [DW_FORM_flag_present]
999 #       DW_AT_artificial [DW_FORM_flag_present]
1000         - AbbrCode:        0x3
1001           Values:
1002             - Value:           0x1
1003             - Value:           0x1
1004 
1005 #     DW_TAG_subprogram ("f5")
1006 #       DW_AT_declaration [DW_FORM_flag_present]
1007 #       DW_AT_artificial [DW_FORM_flag_present]
1008         - AbbrCode:        0x3
1009           Values:
1010             - Value:           0x1
1011             - Value:           0x1
1012 
1013         - AbbrCode: 0x0
1014 ...
1015 )";
1016   YAMLModuleTester t(yamldata);
1017 
1018   DWARFUnit *unit = t.GetDwarfUnit();
1019   ASSERT_NE(unit, nullptr);
1020   const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1021   ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1022   ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1023   DWARFDIE cu_die(unit, cu_entry);
1024 
1025   auto f1 = cu_die.GetFirstChild();
1026   ASSERT_TRUE(f1.IsValid());
1027   ASSERT_EQ(f1.Tag(), DW_TAG_subprogram);
1028 
1029   auto attrs = f1.GetAttributes(DWARFDebugInfoEntry::Recurse::yes);
1030   EXPECT_EQ(attrs.Size(), 7U);
1031   EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_declaration), UINT32_MAX);
1032 }
1033 
1034 INSTANTIATE_TEST_SUITE_P(GetAttributeTests, GetAttributesTestFixture,
1035                          testing::Values(DW_AT_specification,
1036                                          DW_AT_abstract_origin));
1037