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
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::plugin::dwarf;
23using namespace lldb_private::dwarf;
24
25TEST(DWARFDIETest, ChildIteration) {
26 // Tests DWARFDIE::child_iterator.
27
28 const char *yamldata = R"(
29--- !ELF
30FileHeader:
31 Class: ELFCLASS64
32 Data: ELFDATA2LSB
33 Type: ET_EXEC
34 Machine: EM_386
35DWARF:
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
114TEST(DWARFDIETest, PeekName) {
115 const char *yamldata = R"(
116--- !ELF
117FileHeader:
118 Class: ELFCLASS64
119 Data: ELFDATA2LSB
120 Type: ET_EXEC
121 Machine: EM_386
122DWARF:
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>(Val: t.GetModule()->GetSymbolFile());
177 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(idx: 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
195TEST(DWARFDIETest, GetContext) {
196 const char *yamldata = R"(
197--- !ELF
198FileHeader:
199 Class: ELFCLASS64
200 Data: ELFDATA2LSB
201 Type: ET_EXEC
202 Machine: EM_386
203DWARF:
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>(Val: t.GetModule()->GetSymbolFile());
253 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(idx: 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
290TEST(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
312FileHeader:
313 Class: ELFCLASS64
314 Data: ELFDATA2LSB
315 Type: ET_EXEC
316 Machine: EM_386
317DWARF:
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>(Val: t.GetModule()->GetSymbolFile());
375 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(idx: 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
398struct GetAttributesTestFixture : public testing::TestWithParam<dw_attr_t> {};
399
400TEST_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
406FileHeader:
407 Class: ELFCLASS64
408 Data: ELFDATA2LSB
409 Type: ET_EXEC
410 Machine: EM_AARCH64
411DWARF:
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(Fmt: yamldata, Vals: 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(recurse: 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(i: idx, form_value);
514 EXPECT_TRUE(success);
515
516 EXPECT_EQ(form_value.Unsigned(), 0xf00dcafe);
517 }
518}
519
520TEST_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
533FileHeader:
534 Class: ELFCLASS64
535 Data: ELFDATA2LSB
536 Type: ET_EXEC
537 Machine: EM_AARCH64
538DWARF:
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(Fmt: yamldata, Vals: 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(recurse: 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(i: 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(i: 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(i: 2, form_value);
623 ASSERT_TRUE(success);
624
625 EXPECT_EQ(form_value.Reference(), func1);
626 }
627}
628
629TEST_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
636FileHeader:
637 Class: ELFCLASS64
638 Data: ELFDATA2LSB
639 Type: ET_EXEC
640 Machine: EM_AARCH64
641DWARF:
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(Fmt: yamldata, Vals: 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(recurse: 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(attr: DW_AT_sibling);
732 EXPECT_NE(sibling_idx, UINT32_MAX);
733
734 DWARFFormValue form_value;
735 auto success = attrs.ExtractFormValueAtIndex(i: sibling_idx, form_value);
736 ASSERT_TRUE(success);
737
738 EXPECT_EQ(form_value.Unsigned(), 0xdeadbeef);
739}
740
741TEST_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
746FileHeader:
747 Class: ELFCLASS64
748 Data: ELFDATA2LSB
749 Type: ET_EXEC
750 Machine: EM_AARCH64
751DWARF:
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(Fmt: yamldata, Vals: 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(recurse: 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
831TEST_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
837FileHeader:
838 Class: ELFCLASS64
839 Data: ELFDATA2LSB
840 Type: ET_EXEC
841 Machine: EM_AARCH64
842DWARF:
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(Fmt: yamldata, Vals: 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(recurse: 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
917TEST(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
928FileHeader:
929 Class: ELFCLASS64
930 Data: ELFDATA2LSB
931 Type: ET_EXEC
932 Machine: EM_AARCH64
933DWARF:
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(recurse: DWARFDebugInfoEntry::Recurse::yes);
1030 EXPECT_EQ(attrs.Size(), 7U);
1031 EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_declaration), UINT32_MAX);
1032}
1033
1034INSTANTIATE_TEST_SUITE_P(GetAttributeTests, GetAttributesTestFixture,
1035 testing::Values(DW_AT_specification,
1036 DW_AT_abstract_origin));
1037

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp