1 | //===-- MangledTest.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/ObjectFile/ELF/ObjectFileELF.h" |
10 | #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" |
11 | #include "TestingSupport/SubsystemRAII.h" |
12 | #include "TestingSupport/TestUtilities.h" |
13 | |
14 | #include "lldb/Core/Mangled.h" |
15 | #include "lldb/Core/Module.h" |
16 | #include "lldb/Core/ModuleSpec.h" |
17 | #include "lldb/Host/FileSystem.h" |
18 | #include "lldb/Host/HostInfo.h" |
19 | #include "lldb/Symbol/SymbolContext.h" |
20 | |
21 | #include "llvm/Support/FileUtilities.h" |
22 | #include "llvm/Support/Path.h" |
23 | #include "llvm/Support/Program.h" |
24 | #include "llvm/Testing/Support/Error.h" |
25 | |
26 | #include "gtest/gtest.h" |
27 | |
28 | using namespace lldb; |
29 | using namespace lldb_private; |
30 | |
31 | TEST(MangledTest, ResultForValidName) { |
32 | ConstString MangledName("_ZN1a1b1cIiiiEEvm" ); |
33 | Mangled TheMangled(MangledName); |
34 | ConstString TheDemangled = TheMangled.GetDemangledName(); |
35 | |
36 | ConstString ExpectedResult("void a::b::c<int, int, int>(unsigned long)" ); |
37 | EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString()); |
38 | } |
39 | |
40 | TEST(MangledTest, ResultForBlockInvocation) { |
41 | ConstString MangledName("___Z1fU13block_pointerFviE_block_invoke" ); |
42 | Mangled TheMangled(MangledName); |
43 | ConstString TheDemangled = TheMangled.GetDemangledName(); |
44 | |
45 | ConstString ExpectedResult( |
46 | "invocation function for block in f(void (int) block_pointer)" ); |
47 | EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString()); |
48 | } |
49 | |
50 | TEST(MangledTest, EmptyForInvalidName) { |
51 | ConstString MangledName("_ZN1a1b1cmxktpEEvm" ); |
52 | Mangled TheMangled(MangledName); |
53 | ConstString TheDemangled = TheMangled.GetDemangledName(); |
54 | |
55 | EXPECT_STREQ("" , TheDemangled.GetCString()); |
56 | } |
57 | |
58 | TEST(MangledTest, ResultForValidRustV0Name) { |
59 | ConstString mangled_name("_RNvC1a4main" ); |
60 | Mangled the_mangled(mangled_name); |
61 | ConstString the_demangled = the_mangled.GetDemangledName(); |
62 | |
63 | ConstString expected_result("a::main" ); |
64 | EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString()); |
65 | } |
66 | |
67 | TEST(MangledTest, EmptyForInvalidRustV0Name) { |
68 | ConstString mangled_name("_RRR" ); |
69 | Mangled the_mangled(mangled_name); |
70 | ConstString the_demangled = the_mangled.GetDemangledName(); |
71 | |
72 | EXPECT_STREQ("" , the_demangled.GetCString()); |
73 | } |
74 | |
75 | TEST(MangledTest, ResultForValidDLangName) { |
76 | ConstString mangled_name("_Dmain" ); |
77 | Mangled the_mangled(mangled_name); |
78 | ConstString the_demangled = the_mangled.GetDemangledName(); |
79 | |
80 | ConstString expected_result("D main" ); |
81 | EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString()); |
82 | } |
83 | |
84 | TEST(MangledTest, EmptyForInvalidDLangName) { |
85 | ConstString mangled_name("_DDD" ); |
86 | Mangled the_mangled(mangled_name); |
87 | ConstString the_demangled = the_mangled.GetDemangledName(); |
88 | |
89 | EXPECT_STREQ("" , the_demangled.GetCString()); |
90 | } |
91 | |
92 | TEST(MangledTest, RecognizeSwiftMangledNames) { |
93 | llvm::StringRef valid_swift_mangled_names[] = { |
94 | "_TtC4main7MyClass" , // Mangled objc class name |
95 | "_TtP4main3Foo_" , // Mangld objc protocol name |
96 | "$s4main3BarCACycfC" , // Mangled name |
97 | "_$s4main3BarCACycfC" , // Mangled name with leading underscore |
98 | "$S4main3BarCACycfC" , // Older swift mangled name |
99 | "_$S4main3BarCACycfC" , // Older swift mangled name |
100 | // with leading underscore |
101 | // Mangled swift filename |
102 | "@__swiftmacro_4main16FunVariableNames9OptionSetfMm_.swift" , |
103 | }; |
104 | |
105 | for (llvm::StringRef mangled : valid_swift_mangled_names) |
106 | EXPECT_EQ(Mangled::GetManglingScheme(mangled), |
107 | Mangled::eManglingSchemeSwift); |
108 | } |
109 | |
110 | TEST(MangledTest, BoolConversionOperator) { |
111 | { |
112 | ConstString MangledName("_ZN1a1b1cIiiiEEvm" ); |
113 | Mangled TheMangled(MangledName); |
114 | EXPECT_EQ(true, bool(TheMangled)); |
115 | EXPECT_EQ(false, !TheMangled); |
116 | } |
117 | { |
118 | ConstString UnmangledName("puts" ); |
119 | Mangled TheMangled(UnmangledName); |
120 | EXPECT_EQ(true, bool(TheMangled)); |
121 | EXPECT_EQ(false, !TheMangled); |
122 | } |
123 | { |
124 | Mangled TheMangled{}; |
125 | EXPECT_EQ(false, bool(TheMangled)); |
126 | EXPECT_EQ(true, !TheMangled); |
127 | } |
128 | } |
129 | |
130 | TEST(MangledTest, NameIndexes_FindFunctionSymbols) { |
131 | SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab> |
132 | subsystems; |
133 | |
134 | auto ExpectedFile = TestFile::fromYaml(Yaml: R"( |
135 | --- !ELF |
136 | FileHeader: |
137 | Class: ELFCLASS64 |
138 | Data: ELFDATA2LSB |
139 | Type: ET_EXEC |
140 | Machine: EM_X86_64 |
141 | Sections: |
142 | - Name: .text |
143 | Type: SHT_PROGBITS |
144 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] |
145 | AddressAlign: 0x0000000000000010 |
146 | Size: 0x20 |
147 | - Name: .anothertext |
148 | Type: SHT_PROGBITS |
149 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] |
150 | Address: 0x0000000000000010 |
151 | AddressAlign: 0x0000000000000010 |
152 | Size: 0x40 |
153 | - Name: .data |
154 | Type: SHT_PROGBITS |
155 | Flags: [ SHF_WRITE, SHF_ALLOC ] |
156 | Address: 0x00000000000000A8 |
157 | AddressAlign: 0x0000000000000004 |
158 | Content: '01000000' |
159 | Symbols: |
160 | - Name: somedata |
161 | Type: STT_OBJECT |
162 | Section: .anothertext |
163 | Value: 0x0000000000000045 |
164 | Binding: STB_GLOBAL |
165 | - Name: main |
166 | Type: STT_FUNC |
167 | Section: .anothertext |
168 | Value: 0x0000000000000010 |
169 | Size: 0x000000000000003F |
170 | Binding: STB_GLOBAL |
171 | - Name: _Z3foov |
172 | Type: STT_FUNC |
173 | Section: .text |
174 | Size: 0x000000000000000D |
175 | Binding: STB_GLOBAL |
176 | - Name: puts@GLIBC_2.5 |
177 | Type: STT_FUNC |
178 | Section: .text |
179 | Size: 0x000000000000000D |
180 | Binding: STB_GLOBAL |
181 | - Name: puts@GLIBC_2.6 |
182 | Type: STT_FUNC |
183 | Section: .text |
184 | Size: 0x000000000000000D |
185 | Binding: STB_GLOBAL |
186 | - Name: _Z5annotv@VERSION3 |
187 | Type: STT_FUNC |
188 | Section: .text |
189 | Size: 0x000000000000000D |
190 | Binding: STB_GLOBAL |
191 | - Name: _ZN1AC2Ev |
192 | Type: STT_FUNC |
193 | Section: .text |
194 | Size: 0x000000000000000D |
195 | Binding: STB_GLOBAL |
196 | - Name: _ZN1AD2Ev |
197 | Type: STT_FUNC |
198 | Section: .text |
199 | Size: 0x000000000000000D |
200 | Binding: STB_GLOBAL |
201 | - Name: _ZN1A3barEv |
202 | Type: STT_FUNC |
203 | Section: .text |
204 | Size: 0x000000000000000D |
205 | Binding: STB_GLOBAL |
206 | - Name: _ZGVZN4llvm4dbgsEvE7thestrm |
207 | Type: STT_FUNC |
208 | Section: .text |
209 | Size: 0x000000000000000D |
210 | Binding: STB_GLOBAL |
211 | - Name: _ZZN4llvm4dbgsEvE7thestrm |
212 | Type: STT_FUNC |
213 | Section: .text |
214 | Size: 0x000000000000000D |
215 | Binding: STB_GLOBAL |
216 | - Name: _ZTVN5clang4DeclE |
217 | Type: STT_FUNC |
218 | Section: .text |
219 | Size: 0x000000000000000D |
220 | Binding: STB_GLOBAL |
221 | - Name: -[ObjCfoo] |
222 | Type: STT_FUNC |
223 | Section: .text |
224 | Size: 0x000000000000000D |
225 | Binding: STB_GLOBAL |
226 | - Name: +[B ObjCbar(WithCategory)] |
227 | Type: STT_FUNC |
228 | Section: .text |
229 | Size: 0x000000000000000D |
230 | Binding: STB_GLOBAL |
231 | - Name: _Z12undemangableEvx42 |
232 | Type: STT_FUNC |
233 | Section: .text |
234 | Size: 0x000000000000000D |
235 | Binding: STB_GLOBAL |
236 | ... |
237 | )" ); |
238 | ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); |
239 | |
240 | auto M = std::make_shared<Module>(args: ExpectedFile->moduleSpec()); |
241 | |
242 | auto Count = [M](const char *Name, FunctionNameType Type) -> int { |
243 | SymbolContextList SymList; |
244 | M->FindFunctionSymbols(name: ConstString(Name), name_type_mask: Type, sc_list&: SymList); |
245 | return SymList.GetSize(); |
246 | }; |
247 | |
248 | // Unmangled |
249 | EXPECT_EQ(1, Count("main" , eFunctionNameTypeFull)); |
250 | EXPECT_EQ(1, Count("main" , eFunctionNameTypeBase)); |
251 | EXPECT_EQ(0, Count("main" , eFunctionNameTypeMethod)); |
252 | |
253 | // Itanium mangled |
254 | EXPECT_EQ(1, Count("_Z3foov" , eFunctionNameTypeFull)); |
255 | EXPECT_EQ(1, Count("_Z3foov" , eFunctionNameTypeBase)); |
256 | EXPECT_EQ(1, Count("foo" , eFunctionNameTypeBase)); |
257 | EXPECT_EQ(0, Count("foo" , eFunctionNameTypeMethod)); |
258 | |
259 | // Unmangled with linker annotation |
260 | EXPECT_EQ(1, Count("puts@GLIBC_2.5" , eFunctionNameTypeFull)); |
261 | EXPECT_EQ(1, Count("puts@GLIBC_2.6" , eFunctionNameTypeFull)); |
262 | EXPECT_EQ(2, Count("puts" , eFunctionNameTypeFull)); |
263 | EXPECT_EQ(2, Count("puts" , eFunctionNameTypeBase)); |
264 | EXPECT_EQ(0, Count("puts" , eFunctionNameTypeMethod)); |
265 | |
266 | // Itanium mangled with linker annotation |
267 | EXPECT_EQ(1, Count("_Z5annotv@VERSION3" , eFunctionNameTypeFull)); |
268 | EXPECT_EQ(1, Count("_Z5annotv" , eFunctionNameTypeFull)); |
269 | EXPECT_EQ(1, Count("_Z5annotv" , eFunctionNameTypeBase)); |
270 | EXPECT_EQ(0, Count("annot" , eFunctionNameTypeBase)); |
271 | EXPECT_EQ(0, Count("annot" , eFunctionNameTypeMethod)); |
272 | |
273 | // Itanium mangled ctor A::A() |
274 | EXPECT_EQ(1, Count("_ZN1AC2Ev" , eFunctionNameTypeFull)); |
275 | EXPECT_EQ(1, Count("_ZN1AC2Ev" , eFunctionNameTypeBase)); |
276 | EXPECT_EQ(1, Count("A" , eFunctionNameTypeMethod)); |
277 | EXPECT_EQ(0, Count("A" , eFunctionNameTypeBase)); |
278 | |
279 | // Itanium mangled dtor A::~A() |
280 | EXPECT_EQ(1, Count("_ZN1AD2Ev" , eFunctionNameTypeFull)); |
281 | EXPECT_EQ(1, Count("_ZN1AD2Ev" , eFunctionNameTypeBase)); |
282 | EXPECT_EQ(1, Count("~A" , eFunctionNameTypeMethod)); |
283 | EXPECT_EQ(0, Count("~A" , eFunctionNameTypeBase)); |
284 | |
285 | // Itanium mangled method A::bar() |
286 | EXPECT_EQ(1, Count("_ZN1A3barEv" , eFunctionNameTypeFull)); |
287 | EXPECT_EQ(1, Count("_ZN1A3barEv" , eFunctionNameTypeBase)); |
288 | EXPECT_EQ(1, Count("bar" , eFunctionNameTypeMethod)); |
289 | EXPECT_EQ(0, Count("bar" , eFunctionNameTypeBase)); |
290 | |
291 | // Itanium mangled names that are explicitly excluded from parsing |
292 | EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm" , eFunctionNameTypeFull)); |
293 | EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm" , eFunctionNameTypeBase)); |
294 | EXPECT_EQ(0, Count("dbgs" , eFunctionNameTypeMethod)); |
295 | EXPECT_EQ(0, Count("dbgs" , eFunctionNameTypeBase)); |
296 | EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm" , eFunctionNameTypeFull)); |
297 | EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm" , eFunctionNameTypeBase)); |
298 | EXPECT_EQ(0, Count("dbgs" , eFunctionNameTypeMethod)); |
299 | EXPECT_EQ(0, Count("dbgs" , eFunctionNameTypeBase)); |
300 | EXPECT_EQ(1, Count("_ZTVN5clang4DeclE" , eFunctionNameTypeFull)); |
301 | EXPECT_EQ(1, Count("_ZTVN5clang4DeclE" , eFunctionNameTypeBase)); |
302 | EXPECT_EQ(0, Count("Decl" , eFunctionNameTypeMethod)); |
303 | EXPECT_EQ(0, Count("Decl" , eFunctionNameTypeBase)); |
304 | |
305 | // ObjC mangled static |
306 | EXPECT_EQ(1, Count("-[ObjCfoo]" , eFunctionNameTypeFull)); |
307 | EXPECT_EQ(1, Count("-[ObjCfoo]" , eFunctionNameTypeBase)); |
308 | EXPECT_EQ(0, Count("ObjCfoo" , eFunctionNameTypeMethod)); |
309 | |
310 | // ObjC mangled method with category |
311 | EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]" , eFunctionNameTypeFull)); |
312 | EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]" , eFunctionNameTypeBase)); |
313 | EXPECT_EQ(0, Count("ObjCbar" , eFunctionNameTypeMethod)); |
314 | |
315 | // Invalid things: unable to decode but still possible to find by full name |
316 | EXPECT_EQ(1, Count("_Z12undemangableEvx42" , eFunctionNameTypeFull)); |
317 | EXPECT_EQ(1, Count("_Z12undemangableEvx42" , eFunctionNameTypeBase)); |
318 | EXPECT_EQ(0, Count("_Z12undemangableEvx42" , eFunctionNameTypeMethod)); |
319 | EXPECT_EQ(0, Count("undemangable" , eFunctionNameTypeBase)); |
320 | EXPECT_EQ(0, Count("undemangable" , eFunctionNameTypeMethod)); |
321 | } |
322 | |