1 | //===-- Mangled.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 "lldb/Core/Mangled.h" |
10 | |
11 | #include "lldb/Core/RichManglingContext.h" |
12 | #include "lldb/Utility/ConstString.h" |
13 | #include "lldb/Utility/Log.h" |
14 | #include "lldb/Utility/Logging.h" |
15 | #include "lldb/Utility/RegularExpression.h" |
16 | #include "lldb/Utility/Stream.h" |
17 | #include "lldb/lldb-enumerations.h" |
18 | |
19 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" |
20 | #include "Plugins/Language/ObjC/ObjCLanguage.h" |
21 | |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/Demangle/Demangle.h" |
24 | #include "llvm/Support/Compiler.h" |
25 | |
26 | #include <mutex> |
27 | #include <string> |
28 | #include <utility> |
29 | |
30 | #include <stdlib.h> |
31 | #include <string.h> |
32 | using namespace lldb_private; |
33 | |
34 | static inline bool cstring_is_mangled(llvm::StringRef s) { |
35 | return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone; |
36 | } |
37 | |
38 | static ConstString |
39 | get_demangled_name_without_arguments(ConstString mangled, |
40 | ConstString demangled) { |
41 | // This pair is <mangled name, demangled name without function arguments> |
42 | static std::pair<ConstString, ConstString> |
43 | g_most_recent_mangled_to_name_sans_args; |
44 | |
45 | // Need to have the mangled & demangled names we're currently examining as |
46 | // statics so we can return a const ref to them at the end of the func if we |
47 | // don't have anything better. |
48 | static ConstString g_last_mangled; |
49 | static ConstString g_last_demangled; |
50 | |
51 | if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) { |
52 | return g_most_recent_mangled_to_name_sans_args.second; |
53 | } |
54 | |
55 | g_last_demangled = demangled; |
56 | g_last_mangled = mangled; |
57 | |
58 | const char *mangled_name_cstr = mangled.GetCString(); |
59 | |
60 | if (demangled && mangled_name_cstr && mangled_name_cstr[0]) { |
61 | if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && |
62 | (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, |
63 | // typeinfo structure, and typeinfo |
64 | // mangled_name |
65 | mangled_name_cstr[2] != 'G' && // avoid guard variables |
66 | mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually |
67 | // handle eSymbolTypeData, we will want |
68 | // this back) |
69 | { |
70 | CPlusPlusLanguage::MethodName cxx_method(demangled); |
71 | if (!cxx_method.GetBasename().empty()) { |
72 | std::string shortname; |
73 | if (!cxx_method.GetContext().empty()) |
74 | shortname = cxx_method.GetContext().str() + "::" ; |
75 | shortname += cxx_method.GetBasename().str(); |
76 | ConstString result(shortname.c_str()); |
77 | g_most_recent_mangled_to_name_sans_args.first = mangled; |
78 | g_most_recent_mangled_to_name_sans_args.second = result; |
79 | return g_most_recent_mangled_to_name_sans_args.second; |
80 | } |
81 | } |
82 | } |
83 | |
84 | if (demangled) |
85 | return g_last_demangled; |
86 | return g_last_mangled; |
87 | } |
88 | |
89 | #pragma mark Mangled |
90 | |
91 | Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { |
92 | if (name.empty()) |
93 | return Mangled::eManglingSchemeNone; |
94 | |
95 | if (name.startswith("?" )) |
96 | return Mangled::eManglingSchemeMSVC; |
97 | |
98 | if (name.startswith("_Z" )) |
99 | return Mangled::eManglingSchemeItanium; |
100 | |
101 | // ___Z is a clang extension of block invocations |
102 | if (name.startswith("___Z" )) |
103 | return Mangled::eManglingSchemeItanium; |
104 | |
105 | return Mangled::eManglingSchemeNone; |
106 | } |
107 | |
108 | Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() { |
109 | if (s) |
110 | SetValue(s); |
111 | } |
112 | |
113 | Mangled::Mangled(llvm::StringRef name) { |
114 | if (!name.empty()) |
115 | SetValue(ConstString(name)); |
116 | } |
117 | |
118 | // Convert to pointer operator. This allows code to check any Mangled objects |
119 | // to see if they contain anything valid using code such as: |
120 | // |
121 | // Mangled mangled(...); |
122 | // if (mangled) |
123 | // { ... |
124 | Mangled::operator void *() const { |
125 | return (m_mangled) ? const_cast<Mangled *>(this) : nullptr; |
126 | } |
127 | |
128 | // Logical NOT operator. This allows code to check any Mangled objects to see |
129 | // if they are invalid using code such as: |
130 | // |
131 | // Mangled mangled(...); |
132 | // if (!file_spec) |
133 | // { ... |
134 | bool Mangled::operator!() const { return !m_mangled; } |
135 | |
136 | // Clear the mangled and demangled values. |
137 | void Mangled::Clear() { |
138 | m_mangled.Clear(); |
139 | m_demangled.Clear(); |
140 | } |
141 | |
142 | // Compare the string values. |
143 | int Mangled::Compare(const Mangled &a, const Mangled &b) { |
144 | return ConstString::Compare(a.GetName(ePreferMangled), |
145 | b.GetName(ePreferMangled)); |
146 | } |
147 | |
148 | // Set the string value in this objects. If "mangled" is true, then the mangled |
149 | // named is set with the new value in "s", else the demangled name is set. |
150 | void Mangled::SetValue(ConstString s, bool mangled) { |
151 | if (s) { |
152 | if (mangled) { |
153 | m_demangled.Clear(); |
154 | m_mangled = s; |
155 | } else { |
156 | m_demangled = s; |
157 | m_mangled.Clear(); |
158 | } |
159 | } else { |
160 | m_demangled.Clear(); |
161 | m_mangled.Clear(); |
162 | } |
163 | } |
164 | |
165 | void Mangled::SetValue(ConstString name) { |
166 | if (name) { |
167 | if (cstring_is_mangled(name.GetStringRef())) { |
168 | m_demangled.Clear(); |
169 | m_mangled = name; |
170 | } else { |
171 | m_demangled = name; |
172 | m_mangled.Clear(); |
173 | } |
174 | } else { |
175 | m_demangled.Clear(); |
176 | m_mangled.Clear(); |
177 | } |
178 | } |
179 | |
180 | // Local helpers for different demangling implementations. |
181 | static char *GetMSVCDemangledStr(const char *M) { |
182 | char *demangled_cstr = llvm::microsoftDemangle( |
183 | M, nullptr, nullptr, nullptr, nullptr, |
184 | llvm::MSDemangleFlags(llvm::MSDF_NoAccessSpecifier | |
185 | llvm::MSDF_NoCallingConvention | |
186 | llvm::MSDF_NoMemberType)); |
187 | |
188 | if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { |
189 | if (demangled_cstr && demangled_cstr[0]) |
190 | LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"" , M, demangled_cstr); |
191 | else |
192 | LLDB_LOGF(log, "demangled msvc: %s -> error" , M); |
193 | } |
194 | |
195 | return demangled_cstr; |
196 | } |
197 | |
198 | static char *GetItaniumDemangledStr(const char *M) { |
199 | char *demangled_cstr = nullptr; |
200 | |
201 | llvm::ItaniumPartialDemangler ipd; |
202 | bool err = ipd.partialDemangle(M); |
203 | if (!err) { |
204 | // Default buffer and size (will realloc in case it's too small). |
205 | size_t demangled_size = 80; |
206 | demangled_cstr = static_cast<char *>(std::malloc(demangled_size)); |
207 | demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size); |
208 | |
209 | assert(demangled_cstr && |
210 | "finishDemangle must always succeed if partialDemangle did" ); |
211 | assert(demangled_cstr[demangled_size - 1] == '\0' && |
212 | "Expected demangled_size to return length including trailing null" ); |
213 | } |
214 | |
215 | if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { |
216 | if (demangled_cstr) |
217 | LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"" , M, demangled_cstr); |
218 | else |
219 | LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle" , M); |
220 | } |
221 | |
222 | return demangled_cstr; |
223 | } |
224 | |
225 | // Explicit demangling for scheduled requests during batch processing. This |
226 | // makes use of ItaniumPartialDemangler's rich demangle info |
227 | bool Mangled::DemangleWithRichManglingInfo( |
228 | RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) { |
229 | // Others are not meant to arrive here. ObjC names or C's main() for example |
230 | // have their names stored in m_demangled, while m_mangled is empty. |
231 | assert(m_mangled); |
232 | |
233 | // Check whether or not we are interested in this name at all. |
234 | ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef()); |
235 | if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme)) |
236 | return false; |
237 | |
238 | switch (scheme) { |
239 | case eManglingSchemeNone: |
240 | // The current mangled_name_filter would allow llvm_unreachable here. |
241 | return false; |
242 | |
243 | case eManglingSchemeItanium: |
244 | // We want the rich mangling info here, so we don't care whether or not |
245 | // there is a demangled string in the pool already. |
246 | if (context.FromItaniumName(m_mangled)) { |
247 | // If we got an info, we have a name. Copy to string pool and connect the |
248 | // counterparts to accelerate later access in GetDemangledName(). |
249 | context.ParseFullName(); |
250 | m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(), |
251 | m_mangled); |
252 | return true; |
253 | } else { |
254 | m_demangled.SetCString("" ); |
255 | return false; |
256 | } |
257 | |
258 | case eManglingSchemeMSVC: { |
259 | // We have no rich mangling for MSVC-mangled names yet, so first try to |
260 | // demangle it if necessary. |
261 | if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) { |
262 | if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) { |
263 | // If we got an info, we have a name. Copy to string pool and connect |
264 | // the counterparts to accelerate later access in GetDemangledName(). |
265 | m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d), |
266 | m_mangled); |
267 | ::free(d); |
268 | } else { |
269 | m_demangled.SetCString("" ); |
270 | } |
271 | } |
272 | |
273 | if (m_demangled.IsEmpty()) { |
274 | // Cannot demangle it, so don't try parsing. |
275 | return false; |
276 | } else { |
277 | // Demangled successfully, we can try and parse it with |
278 | // CPlusPlusLanguage::MethodName. |
279 | return context.FromCxxMethodName(m_demangled); |
280 | } |
281 | } |
282 | } |
283 | llvm_unreachable("Fully covered switch above!" ); |
284 | } |
285 | |
286 | // Generate the demangled name on demand using this accessor. Code in this |
287 | // class will need to use this accessor if it wishes to decode the demangled |
288 | // name. The result is cached and will be kept until a new string value is |
289 | // supplied to this object, or until the end of the object's lifetime. |
290 | ConstString Mangled::GetDemangledName() const { |
291 | // Check to make sure we have a valid mangled name and that we haven't |
292 | // already decoded our mangled name. |
293 | if (m_mangled && m_demangled.IsNull()) { |
294 | // Don't bother running anything that isn't mangled |
295 | const char *mangled_name = m_mangled.GetCString(); |
296 | ManglingScheme mangling_scheme = GetManglingScheme(m_mangled.GetStringRef()); |
297 | if (mangling_scheme != eManglingSchemeNone && |
298 | !m_mangled.GetMangledCounterpart(m_demangled)) { |
299 | // We didn't already mangle this name, demangle it and if all goes well |
300 | // add it to our map. |
301 | char *demangled_name = nullptr; |
302 | switch (mangling_scheme) { |
303 | case eManglingSchemeMSVC: |
304 | demangled_name = GetMSVCDemangledStr(mangled_name); |
305 | break; |
306 | case eManglingSchemeItanium: { |
307 | demangled_name = GetItaniumDemangledStr(mangled_name); |
308 | break; |
309 | } |
310 | case eManglingSchemeNone: |
311 | llvm_unreachable("eManglingSchemeNone was handled already" ); |
312 | } |
313 | if (demangled_name) { |
314 | m_demangled.SetStringWithMangledCounterpart( |
315 | llvm::StringRef(demangled_name), m_mangled); |
316 | free(demangled_name); |
317 | } |
318 | } |
319 | if (m_demangled.IsNull()) { |
320 | // Set the demangled string to the empty string to indicate we tried to |
321 | // parse it once and failed. |
322 | m_demangled.SetCString("" ); |
323 | } |
324 | } |
325 | |
326 | return m_demangled; |
327 | } |
328 | |
329 | ConstString |
330 | Mangled::GetDisplayDemangledName() const { |
331 | return GetDemangledName(); |
332 | } |
333 | |
334 | bool Mangled::NameMatches(const RegularExpression ®ex) const { |
335 | if (m_mangled && regex.Execute(m_mangled.GetStringRef())) |
336 | return true; |
337 | |
338 | ConstString demangled = GetDemangledName(); |
339 | return demangled && regex.Execute(demangled.GetStringRef()); |
340 | } |
341 | |
342 | // Get the demangled name if there is one, else return the mangled name. |
343 | ConstString Mangled::GetName(Mangled::NamePreference preference) const { |
344 | if (preference == ePreferMangled && m_mangled) |
345 | return m_mangled; |
346 | |
347 | ConstString demangled = GetDemangledName(); |
348 | |
349 | if (preference == ePreferDemangledWithoutArguments) { |
350 | return get_demangled_name_without_arguments(m_mangled, demangled); |
351 | } |
352 | if (preference == ePreferDemangled) { |
353 | // Call the accessor to make sure we get a demangled name in case it hasn't |
354 | // been demangled yet... |
355 | if (demangled) |
356 | return demangled; |
357 | return m_mangled; |
358 | } |
359 | return demangled; |
360 | } |
361 | |
362 | // Dump a Mangled object to stream "s". We don't force our demangled name to be |
363 | // computed currently (we don't use the accessor). |
364 | void Mangled::Dump(Stream *s) const { |
365 | if (m_mangled) { |
366 | *s << ", mangled = " << m_mangled; |
367 | } |
368 | if (m_demangled) { |
369 | const char *demangled = m_demangled.AsCString(); |
370 | s->Printf(", demangled = %s" , demangled[0] ? demangled : "<error>" ); |
371 | } |
372 | } |
373 | |
374 | // Dumps a debug version of this string with extra object and state information |
375 | // to stream "s". |
376 | void Mangled::DumpDebug(Stream *s) const { |
377 | s->Printf("%*p: Mangled mangled = " , static_cast<int>(sizeof(void *) * 2), |
378 | static_cast<const void *>(this)); |
379 | m_mangled.DumpDebug(s); |
380 | s->Printf(", demangled = " ); |
381 | m_demangled.DumpDebug(s); |
382 | } |
383 | |
384 | // Return the size in byte that this object takes in memory. The size includes |
385 | // the size of the objects it owns, and not the strings that it references |
386 | // because they are shared strings. |
387 | size_t Mangled::MemorySize() const { |
388 | return m_mangled.MemorySize() + m_demangled.MemorySize(); |
389 | } |
390 | |
391 | // We "guess" the language because we can't determine a symbol's language from |
392 | // it's name. For example, a Pascal symbol can be mangled using the C++ |
393 | // Itanium scheme, and defined in a compilation unit within the same module as |
394 | // other C++ units. In addition, different targets could have different ways |
395 | // of mangling names from a given language, likewise the compilation units |
396 | // within those targets. |
397 | lldb::LanguageType Mangled::GuessLanguage() const { |
398 | ConstString mangled = GetMangledName(); |
399 | |
400 | if (mangled) { |
401 | const char *mangled_name = mangled.GetCString(); |
402 | if (CPlusPlusLanguage::IsCPPMangledName(mangled_name)) |
403 | return lldb::eLanguageTypeC_plus_plus; |
404 | } else { |
405 | // ObjC names aren't really mangled, so they won't necessarily be in the |
406 | // mangled name slot. |
407 | ConstString demangled_name = GetDemangledName(); |
408 | if (demangled_name |
409 | && ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString())) |
410 | return lldb::eLanguageTypeObjC; |
411 | |
412 | } |
413 | return lldb::eLanguageTypeUnknown; |
414 | } |
415 | |
416 | // Dump OBJ to the supplied stream S. |
417 | Stream &operator<<(Stream &s, const Mangled &obj) { |
418 | if (obj.GetMangledName()) |
419 | s << "mangled = '" << obj.GetMangledName() << "'" ; |
420 | |
421 | ConstString demangled = obj.GetDemangledName(); |
422 | if (demangled) |
423 | s << ", demangled = '" << demangled << '\''; |
424 | else |
425 | s << ", demangled = <error>" ; |
426 | return s; |
427 | } |
428 | |