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
18using namespace lldb;
19using namespace lldb_private;
20using namespace lldb_private::plugin::dwarf;
21using StringRef = llvm::StringRef;
22
23static void
24check_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
36static DWARFDeclContext::Entry make_entry(const char *c) {
37 return DWARFDeclContext::Entry(dwarf::DW_TAG_class_type, c);
38}
39
40TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithIDXParent) {
41 const char *yamldata = R"(
42--- !ELF
43FileHeader:
44 Class: ELFCLASS64
45 Data: ELFDATA2LSB
46 Type: ET_EXEC
47 Machine: EM_386
48DWARF:
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
132TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithoutIDXParent) {
133 const char *yamldata = R"(
134--- !ELF
135FileHeader:
136 Class: ELFCLASS64
137 Data: ELFDATA2LSB
138 Type: ET_EXEC
139 Machine: EM_386
140DWARF:
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

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