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 "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h" |
13 | #include "TestingSupport/Symbol/YAMLModuleTester.h" |
14 | #include "llvm/ADT/STLExtras.h" |
15 | #include "gmock/gmock.h" |
16 | #include "gtest/gtest.h" |
17 | |
18 | using namespace lldb; |
19 | using namespace lldb_private; |
20 | using namespace lldb_private::plugin::dwarf; |
21 | using StringRef = llvm::StringRef; |
22 | |
23 | static void |
24 | check_num_matches(DebugNamesDWARFIndex &index, int expected_num_matches, |
25 | llvm::ArrayRef<DWARFDeclContext::Entry> ctx_entries) { |
26 | DWARFDeclContext ctx(ctx_entries); |
27 | int num_matches = 0; |
28 | |
29 | index.GetFullyQualifiedType(context: ctx, callback: [&](DWARFDIE die) { |
30 | num_matches++; |
31 | return true; |
32 | }); |
33 | ASSERT_EQ(num_matches, expected_num_matches); |
34 | } |
35 | |
36 | static DWARFDeclContext::Entry make_entry(const char *c) { |
37 | return DWARFDeclContext::Entry(dwarf::DW_TAG_class_type, c); |
38 | } |
39 | |
40 | TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithIDXParent) { |
41 | const char *yamldata = R"( |
42 | --- !ELF |
43 | FileHeader: |
44 | Class: ELFCLASS64 |
45 | Data: ELFDATA2LSB |
46 | Type: ET_EXEC |
47 | Machine: EM_386 |
48 | DWARF: |
49 | debug_str: |
50 | - '1' |
51 | - '2' |
52 | - '3' |
53 | debug_abbrev: |
54 | - Table: |
55 | # We intentionally don't nest types in debug_info: if the nesting is not |
56 | # inferred from debug_names, we want the test to fail. |
57 | - Code: 0x1 |
58 | Tag: DW_TAG_compile_unit |
59 | Children: DW_CHILDREN_yes |
60 | - Code: 0x2 |
61 | Tag: DW_TAG_class_type |
62 | Children: DW_CHILDREN_no |
63 | Attributes: |
64 | - Attribute: DW_AT_name |
65 | Form: DW_FORM_strp |
66 | debug_info: |
67 | - Version: 4 |
68 | AddrSize: 8 |
69 | Entries: |
70 | - AbbrCode: 0x1 |
71 | - AbbrCode: 0x2 |
72 | Values: |
73 | - Value: 0x0 # Name "1" |
74 | - AbbrCode: 0x2 |
75 | Values: |
76 | - Value: 0x2 # Name "2" |
77 | - AbbrCode: 0x2 |
78 | Values: |
79 | - Value: 0x4 # Name "3" |
80 | - AbbrCode: 0x0 |
81 | debug_names: |
82 | Abbreviations: |
83 | - Code: 0x11 |
84 | Tag: DW_TAG_class_type |
85 | Indices: |
86 | - Idx: DW_IDX_parent |
87 | Form: DW_FORM_flag_present |
88 | - Idx: DW_IDX_die_offset |
89 | Form: DW_FORM_ref4 |
90 | - Code: 0x22 |
91 | Tag: DW_TAG_class_type |
92 | Indices: |
93 | - Idx: DW_IDX_parent |
94 | Form: DW_FORM_ref4 |
95 | - Idx: DW_IDX_die_offset |
96 | Form: DW_FORM_ref4 |
97 | Entries: |
98 | - Name: 0x0 # strp to Name1 |
99 | Code: 0x11 |
100 | Values: |
101 | - 0xc # Die offset to entry named "1" |
102 | - Name: 0x2 # strp to Name2 |
103 | Code: 0x22 |
104 | Values: |
105 | - 0x0 # Parent = First entry ("1") |
106 | - 0x11 # Die offset to entry named "1:2" |
107 | - Name: 0x4 # strp to Name3 |
108 | Code: 0x22 |
109 | Values: |
110 | - 0x6 # Parent = Second entry ("1::2") |
111 | - 0x16 # Die offset to entry named "1::2::3" |
112 | - Name: 0x4 # strp to Name3 |
113 | Code: 0x11 |
114 | Values: |
115 | - 0x16 # Die offset to entry named "3" |
116 | )" ; |
117 | |
118 | YAMLModuleTester t(yamldata); |
119 | auto *symbol_file = |
120 | llvm::cast<SymbolFileDWARF>(Val: t.GetModule()->GetSymbolFile()); |
121 | auto *index = static_cast<DebugNamesDWARFIndex *>(symbol_file->getIndex()); |
122 | ASSERT_NE(index, nullptr); |
123 | |
124 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "1" )}); |
125 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "2" ), make_entry(c: "1" )}); |
126 | check_num_matches(index&: *index, expected_num_matches: 1, |
127 | ctx_entries: {make_entry(c: "3" ), make_entry(c: "2" ), make_entry(c: "1" )}); |
128 | check_num_matches(index&: *index, expected_num_matches: 0, ctx_entries: {make_entry(c: "2" )}); |
129 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "3" )}); |
130 | } |
131 | |
132 | TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithoutIDXParent) { |
133 | const char *yamldata = R"( |
134 | --- !ELF |
135 | FileHeader: |
136 | Class: ELFCLASS64 |
137 | Data: ELFDATA2LSB |
138 | Type: ET_EXEC |
139 | Machine: EM_386 |
140 | DWARF: |
141 | debug_str: |
142 | - '1' |
143 | - '2' |
144 | debug_abbrev: |
145 | - Table: |
146 | - Code: 0x1 |
147 | Tag: DW_TAG_compile_unit |
148 | Children: DW_CHILDREN_yes |
149 | - Code: 0x2 |
150 | Tag: DW_TAG_class_type |
151 | Children: DW_CHILDREN_yes |
152 | Attributes: |
153 | - Attribute: DW_AT_name |
154 | Form: DW_FORM_strp |
155 | - Code: 0x3 |
156 | Tag: DW_TAG_class_type |
157 | Children: DW_CHILDREN_no |
158 | Attributes: |
159 | - Attribute: DW_AT_name |
160 | Form: DW_FORM_strp |
161 | debug_info: |
162 | - Version: 4 |
163 | AddrSize: 8 |
164 | Entries: |
165 | - AbbrCode: 0x1 |
166 | - AbbrCode: 0x2 |
167 | Values: |
168 | - Value: 0x0 # Name "1" |
169 | - AbbrCode: 0x3 |
170 | Values: |
171 | - Value: 0x2 # Name "2" |
172 | - AbbrCode: 0x0 |
173 | - AbbrCode: 0x3 |
174 | Values: |
175 | - Value: 0x2 # Name "2" |
176 | - AbbrCode: 0x0 |
177 | debug_names: |
178 | Abbreviations: |
179 | - Code: 0x1 |
180 | Tag: DW_TAG_class_type |
181 | Indices: |
182 | - Idx: DW_IDX_die_offset |
183 | Form: DW_FORM_ref4 |
184 | Entries: |
185 | - Name: 0x0 # strp to Name1 |
186 | Code: 0x1 |
187 | Values: |
188 | - 0xc # Die offset to entry named "1" |
189 | - Name: 0x2 # strp to Name2 |
190 | Code: 0x1 |
191 | Values: |
192 | - 0x11 # Die offset to entry named "1::2" |
193 | - Name: 0x2 # strp to Name2 |
194 | Code: 0x1 |
195 | Values: |
196 | - 0x17 # Die offset to entry named "2" |
197 | )" ; |
198 | |
199 | YAMLModuleTester t(yamldata); |
200 | auto *symbol_file = |
201 | llvm::cast<SymbolFileDWARF>(Val: t.GetModule()->GetSymbolFile()); |
202 | auto *index = static_cast<DebugNamesDWARFIndex *>(symbol_file->getIndex()); |
203 | ASSERT_NE(index, nullptr); |
204 | |
205 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "1" )}); |
206 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "2" ), make_entry(c: "1" )}); |
207 | check_num_matches(index&: *index, expected_num_matches: 1, ctx_entries: {make_entry(c: "2" )}); |
208 | } |
209 | |