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 "TestingSupport/Symbol/YAMLModuleTester.h" |
12 | #include "llvm/ADT/STLExtras.h" |
13 | #include "gmock/gmock.h" |
14 | #include "gtest/gtest.h" |
15 | |
16 | using namespace lldb; |
17 | using namespace lldb_private; |
18 | using namespace lldb_private::plugin::dwarf; |
19 | |
20 | TEST(DWARFDIETest, ChildIteration) { |
21 | // Tests DWARFDIE::child_iterator. |
22 | |
23 | const char *yamldata = R"( |
24 | --- !ELF |
25 | FileHeader: |
26 | Class: ELFCLASS64 |
27 | Data: ELFDATA2LSB |
28 | Type: ET_EXEC |
29 | Machine: EM_386 |
30 | DWARF: |
31 | debug_abbrev: |
32 | - Table: |
33 | - Code: 0x00000001 |
34 | Tag: DW_TAG_compile_unit |
35 | Children: DW_CHILDREN_yes |
36 | Attributes: |
37 | - Attribute: DW_AT_language |
38 | Form: DW_FORM_data2 |
39 | - Code: 0x00000002 |
40 | Tag: DW_TAG_base_type |
41 | Children: DW_CHILDREN_no |
42 | Attributes: |
43 | - Attribute: DW_AT_encoding |
44 | Form: DW_FORM_data1 |
45 | - Attribute: DW_AT_byte_size |
46 | Form: DW_FORM_data1 |
47 | debug_info: |
48 | - Version: 4 |
49 | AddrSize: 8 |
50 | Entries: |
51 | - AbbrCode: 0x00000001 |
52 | Values: |
53 | - Value: 0x000000000000000C |
54 | - AbbrCode: 0x00000002 |
55 | Values: |
56 | - Value: 0x0000000000000007 # DW_ATE_unsigned |
57 | - Value: 0x0000000000000004 |
58 | - AbbrCode: 0x00000002 |
59 | Values: |
60 | - Value: 0x0000000000000007 # DW_ATE_unsigned |
61 | - Value: 0x0000000000000008 |
62 | - AbbrCode: 0x00000002 |
63 | Values: |
64 | - Value: 0x0000000000000005 # DW_ATE_signed |
65 | - Value: 0x0000000000000008 |
66 | - AbbrCode: 0x00000000 |
67 | )" ; |
68 | |
69 | YAMLModuleTester t(yamldata); |
70 | ASSERT_TRUE((bool)t.GetDwarfUnit()); |
71 | |
72 | DWARFUnit *unit = t.GetDwarfUnit(); |
73 | const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE(); |
74 | |
75 | // Create a DWARFDIE that has three DW_TAG_base_type children. |
76 | DWARFDIE top_die(unit, die_first); |
77 | |
78 | // Create the iterator range that has the three tags as elements. |
79 | llvm::iterator_range<DWARFDIE::child_iterator> children = top_die.children(); |
80 | |
81 | // Compare begin() to the first child DIE. |
82 | DWARFDIE::child_iterator child_iter = children.begin(); |
83 | ASSERT_NE(child_iter, children.end()); |
84 | const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild(); |
85 | EXPECT_EQ((*child_iter).GetDIE(), die_child0); |
86 | |
87 | // Step to the second child DIE. |
88 | ++child_iter; |
89 | ASSERT_NE(child_iter, children.end()); |
90 | const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling(); |
91 | EXPECT_EQ((*child_iter).GetDIE(), die_child1); |
92 | |
93 | // Step to the third child DIE. |
94 | ++child_iter; |
95 | ASSERT_NE(child_iter, children.end()); |
96 | const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling(); |
97 | EXPECT_EQ((*child_iter).GetDIE(), die_child2); |
98 | |
99 | // Step to the end of the range. |
100 | ++child_iter; |
101 | EXPECT_EQ(child_iter, children.end()); |
102 | |
103 | // Take one of the DW_TAG_base_type DIEs (which has no children) and make |
104 | // sure the children range is now empty. |
105 | DWARFDIE no_children_die(unit, die_child0); |
106 | EXPECT_TRUE(no_children_die.children().empty()); |
107 | } |
108 | |
109 | TEST(DWARFDIETest, PeekName) { |
110 | const char *yamldata = R"( |
111 | --- !ELF |
112 | FileHeader: |
113 | Class: ELFCLASS64 |
114 | Data: ELFDATA2LSB |
115 | Type: ET_EXEC |
116 | Machine: EM_386 |
117 | DWARF: |
118 | debug_str: |
119 | - 'NameType1' |
120 | - 'NameType2' |
121 | debug_abbrev: |
122 | - Table: |
123 | - Code: 0x00000001 |
124 | Tag: DW_TAG_compile_unit |
125 | Children: DW_CHILDREN_yes |
126 | Attributes: |
127 | - Attribute: DW_AT_language |
128 | Form: DW_FORM_data2 |
129 | - Code: 0x00000002 |
130 | Tag: DW_TAG_base_type |
131 | Children: DW_CHILDREN_no |
132 | Attributes: |
133 | - Attribute: DW_AT_name |
134 | Form: DW_FORM_strp |
135 | - Code: 0x00000003 |
136 | Tag: DW_TAG_base_type |
137 | Children: DW_CHILDREN_no |
138 | Attributes: |
139 | - Attribute: DW_AT_abstract_origin |
140 | Form: DW_FORM_ref1 |
141 | - Code: 0x00000004 |
142 | Tag: DW_TAG_base_type |
143 | Children: DW_CHILDREN_no |
144 | Attributes: |
145 | - Attribute: DW_AT_specification |
146 | Form: DW_FORM_ref1 |
147 | debug_info: |
148 | - Version: 4 |
149 | AddrSize: 8 |
150 | Entries: |
151 | - AbbrCode: 0x00000001 |
152 | Values: |
153 | - Value: 0x000000000000000C |
154 | - AbbrCode: 0x00000002 |
155 | Values: |
156 | - Value: 0x0000000000000000 # Name = NameType1 |
157 | - AbbrCode: 0x00000002 |
158 | Values: |
159 | - Value: 0x000000000000000a # Name = NameType2 |
160 | - AbbrCode: 0x00000003 |
161 | Values: |
162 | - Value: 0x000000000000000e # Ref abstract origin to NameType1 DIE. |
163 | - AbbrCode: 0x00000004 |
164 | Values: |
165 | - Value: 0x0000000000000013 # Ref specification to NameType2 DIE. |
166 | - AbbrCode: 0x00000000 |
167 | )" ; |
168 | |
169 | YAMLModuleTester t(yamldata); |
170 | auto *symbol_file = |
171 | llvm::cast<SymbolFileDWARF>(Val: t.GetModule()->GetSymbolFile()); |
172 | auto &debug_info = symbol_file->DebugInfo(); |
173 | |
174 | DIERef first_die(std::nullopt, DIERef::Section::DebugInfo, |
175 | 11 /*FirstDIEOffset*/); |
176 | EXPECT_EQ(debug_info.PeekDIEName(first_die), "" ); |
177 | |
178 | DIERef second_die(std::nullopt, DIERef::Section::DebugInfo, 14); |
179 | EXPECT_EQ(debug_info.PeekDIEName(second_die), "NameType1" ); |
180 | |
181 | DIERef third_die(std::nullopt, DIERef::Section::DebugInfo, 19); |
182 | EXPECT_EQ(debug_info.PeekDIEName(third_die), "NameType2" ); |
183 | |
184 | DIERef fourth_die(std::nullopt, DIERef::Section::DebugInfo, 24); |
185 | EXPECT_EQ(debug_info.PeekDIEName(fourth_die), "NameType1" ); |
186 | |
187 | DIERef fifth_die(std::nullopt, DIERef::Section::DebugInfo, 26); |
188 | EXPECT_EQ(debug_info.PeekDIEName(fifth_die), "NameType2" ); |
189 | } |
190 | |