xref: /openbsd-src/gnu/llvm/lldb/source/Core/Mangled.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- Mangled.cpp -------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/Mangled.h"
10061da546Spatrick 
11*f6aab3d8Srobert #include "lldb/Core/DataFileCache.h"
12061da546Spatrick #include "lldb/Core/RichManglingContext.h"
13*f6aab3d8Srobert #include "lldb/Target/Language.h"
14061da546Spatrick #include "lldb/Utility/ConstString.h"
15*f6aab3d8Srobert #include "lldb/Utility/DataEncoder.h"
16*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick #include "lldb/Utility/RegularExpression.h"
19061da546Spatrick #include "lldb/Utility/Stream.h"
20061da546Spatrick #include "lldb/lldb-enumerations.h"
21061da546Spatrick 
22061da546Spatrick #include "llvm/ADT/StringRef.h"
23061da546Spatrick #include "llvm/Demangle/Demangle.h"
24061da546Spatrick #include "llvm/Support/Compiler.h"
25061da546Spatrick 
26061da546Spatrick #include <mutex>
27061da546Spatrick #include <string>
28061da546Spatrick #include <utility>
29061da546Spatrick 
30be691f3bSpatrick #include <cstdlib>
31be691f3bSpatrick #include <cstring>
32061da546Spatrick using namespace lldb_private;
33061da546Spatrick 
cstring_is_mangled(llvm::StringRef s)34061da546Spatrick static inline bool cstring_is_mangled(llvm::StringRef s) {
35061da546Spatrick   return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
36061da546Spatrick }
37061da546Spatrick 
38061da546Spatrick #pragma mark Mangled
39061da546Spatrick 
GetManglingScheme(llvm::StringRef const name)40061da546Spatrick Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
41061da546Spatrick   if (name.empty())
42061da546Spatrick     return Mangled::eManglingSchemeNone;
43061da546Spatrick 
44061da546Spatrick   if (name.startswith("?"))
45061da546Spatrick     return Mangled::eManglingSchemeMSVC;
46061da546Spatrick 
47be691f3bSpatrick   if (name.startswith("_R"))
48be691f3bSpatrick     return Mangled::eManglingSchemeRustV0;
49be691f3bSpatrick 
50*f6aab3d8Srobert   if (name.startswith("_D"))
51*f6aab3d8Srobert     return Mangled::eManglingSchemeD;
52*f6aab3d8Srobert 
53061da546Spatrick   if (name.startswith("_Z"))
54061da546Spatrick     return Mangled::eManglingSchemeItanium;
55061da546Spatrick 
56061da546Spatrick   // ___Z is a clang extension of block invocations
57061da546Spatrick   if (name.startswith("___Z"))
58061da546Spatrick     return Mangled::eManglingSchemeItanium;
59061da546Spatrick 
60061da546Spatrick   return Mangled::eManglingSchemeNone;
61061da546Spatrick }
62061da546Spatrick 
Mangled(ConstString s)63061da546Spatrick Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
64061da546Spatrick   if (s)
65061da546Spatrick     SetValue(s);
66061da546Spatrick }
67061da546Spatrick 
Mangled(llvm::StringRef name)68061da546Spatrick Mangled::Mangled(llvm::StringRef name) {
69061da546Spatrick   if (!name.empty())
70061da546Spatrick     SetValue(ConstString(name));
71061da546Spatrick }
72061da546Spatrick 
73*f6aab3d8Srobert // Convert to bool operator. This allows code to check any Mangled objects
74061da546Spatrick // to see if they contain anything valid using code such as:
75061da546Spatrick //
76061da546Spatrick //  Mangled mangled(...);
77061da546Spatrick //  if (mangled)
78061da546Spatrick //  { ...
operator bool() const79*f6aab3d8Srobert Mangled::operator bool() const { return m_mangled || m_demangled; }
80061da546Spatrick 
81061da546Spatrick // Clear the mangled and demangled values.
Clear()82061da546Spatrick void Mangled::Clear() {
83061da546Spatrick   m_mangled.Clear();
84061da546Spatrick   m_demangled.Clear();
85061da546Spatrick }
86061da546Spatrick 
87061da546Spatrick // Compare the string values.
Compare(const Mangled & a,const Mangled & b)88061da546Spatrick int Mangled::Compare(const Mangled &a, const Mangled &b) {
89dda28197Spatrick   return ConstString::Compare(a.GetName(ePreferMangled),
90dda28197Spatrick                               b.GetName(ePreferMangled));
91061da546Spatrick }
92061da546Spatrick 
93061da546Spatrick // Set the string value in this objects. If "mangled" is true, then the mangled
94061da546Spatrick // named is set with the new value in "s", else the demangled name is set.
SetValue(ConstString s,bool mangled)95061da546Spatrick void Mangled::SetValue(ConstString s, bool mangled) {
96061da546Spatrick   if (s) {
97061da546Spatrick     if (mangled) {
98061da546Spatrick       m_demangled.Clear();
99061da546Spatrick       m_mangled = s;
100061da546Spatrick     } else {
101061da546Spatrick       m_demangled = s;
102061da546Spatrick       m_mangled.Clear();
103061da546Spatrick     }
104061da546Spatrick   } else {
105061da546Spatrick     m_demangled.Clear();
106061da546Spatrick     m_mangled.Clear();
107061da546Spatrick   }
108061da546Spatrick }
109061da546Spatrick 
SetValue(ConstString name)110061da546Spatrick void Mangled::SetValue(ConstString name) {
111061da546Spatrick   if (name) {
112061da546Spatrick     if (cstring_is_mangled(name.GetStringRef())) {
113061da546Spatrick       m_demangled.Clear();
114061da546Spatrick       m_mangled = name;
115061da546Spatrick     } else {
116061da546Spatrick       m_demangled = name;
117061da546Spatrick       m_mangled.Clear();
118061da546Spatrick     }
119061da546Spatrick   } else {
120061da546Spatrick     m_demangled.Clear();
121061da546Spatrick     m_mangled.Clear();
122061da546Spatrick   }
123061da546Spatrick }
124061da546Spatrick 
125061da546Spatrick // Local helpers for different demangling implementations.
GetMSVCDemangledStr(const char * M)126061da546Spatrick static char *GetMSVCDemangledStr(const char *M) {
127061da546Spatrick   char *demangled_cstr = llvm::microsoftDemangle(
128dda28197Spatrick       M, nullptr, nullptr, nullptr, nullptr,
129*f6aab3d8Srobert       llvm::MSDemangleFlags(
130*f6aab3d8Srobert           llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention |
131*f6aab3d8Srobert           llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType));
132061da546Spatrick 
133*f6aab3d8Srobert   if (Log *log = GetLog(LLDBLog::Demangle)) {
134061da546Spatrick     if (demangled_cstr && demangled_cstr[0])
135061da546Spatrick       LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr);
136061da546Spatrick     else
137061da546Spatrick       LLDB_LOGF(log, "demangled msvc: %s -> error", M);
138061da546Spatrick   }
139061da546Spatrick 
140061da546Spatrick   return demangled_cstr;
141061da546Spatrick }
142061da546Spatrick 
GetItaniumDemangledStr(const char * M)143061da546Spatrick static char *GetItaniumDemangledStr(const char *M) {
144061da546Spatrick   char *demangled_cstr = nullptr;
145061da546Spatrick 
146061da546Spatrick   llvm::ItaniumPartialDemangler ipd;
147061da546Spatrick   bool err = ipd.partialDemangle(M);
148061da546Spatrick   if (!err) {
149061da546Spatrick     // Default buffer and size (will realloc in case it's too small).
150061da546Spatrick     size_t demangled_size = 80;
151061da546Spatrick     demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
152061da546Spatrick     demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
153061da546Spatrick 
154061da546Spatrick     assert(demangled_cstr &&
155061da546Spatrick            "finishDemangle must always succeed if partialDemangle did");
156061da546Spatrick     assert(demangled_cstr[demangled_size - 1] == '\0' &&
157061da546Spatrick            "Expected demangled_size to return length including trailing null");
158061da546Spatrick   }
159061da546Spatrick 
160*f6aab3d8Srobert   if (Log *log = GetLog(LLDBLog::Demangle)) {
161061da546Spatrick     if (demangled_cstr)
162061da546Spatrick       LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
163061da546Spatrick     else
164061da546Spatrick       LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
165061da546Spatrick   }
166061da546Spatrick 
167061da546Spatrick   return demangled_cstr;
168061da546Spatrick }
169061da546Spatrick 
GetRustV0DemangledStr(const char * M)170be691f3bSpatrick static char *GetRustV0DemangledStr(const char *M) {
171*f6aab3d8Srobert   char *demangled_cstr = llvm::rustDemangle(M);
172be691f3bSpatrick 
173*f6aab3d8Srobert   if (Log *log = GetLog(LLDBLog::Demangle)) {
174be691f3bSpatrick     if (demangled_cstr && demangled_cstr[0])
175be691f3bSpatrick       LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr);
176be691f3bSpatrick     else
177be691f3bSpatrick       LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M);
178be691f3bSpatrick   }
179be691f3bSpatrick 
180be691f3bSpatrick   return demangled_cstr;
181be691f3bSpatrick }
182be691f3bSpatrick 
GetDLangDemangledStr(const char * M)183*f6aab3d8Srobert static char *GetDLangDemangledStr(const char *M) {
184*f6aab3d8Srobert   char *demangled_cstr = llvm::dlangDemangle(M);
185*f6aab3d8Srobert 
186*f6aab3d8Srobert   if (Log *log = GetLog(LLDBLog::Demangle)) {
187*f6aab3d8Srobert     if (demangled_cstr && demangled_cstr[0])
188*f6aab3d8Srobert       LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr);
189*f6aab3d8Srobert     else
190*f6aab3d8Srobert       LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M);
191*f6aab3d8Srobert   }
192*f6aab3d8Srobert 
193*f6aab3d8Srobert   return demangled_cstr;
194*f6aab3d8Srobert }
195*f6aab3d8Srobert 
196061da546Spatrick // Explicit demangling for scheduled requests during batch processing. This
197061da546Spatrick // makes use of ItaniumPartialDemangler's rich demangle info
GetRichManglingInfo(RichManglingContext & context,SkipMangledNameFn * skip_mangled_name)198*f6aab3d8Srobert bool Mangled::GetRichManglingInfo(RichManglingContext &context,
199*f6aab3d8Srobert                                   SkipMangledNameFn *skip_mangled_name) {
200061da546Spatrick   // Others are not meant to arrive here. ObjC names or C's main() for example
201061da546Spatrick   // have their names stored in m_demangled, while m_mangled is empty.
202061da546Spatrick   assert(m_mangled);
203061da546Spatrick 
204061da546Spatrick   // Check whether or not we are interested in this name at all.
205061da546Spatrick   ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef());
206061da546Spatrick   if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
207061da546Spatrick     return false;
208061da546Spatrick 
209061da546Spatrick   switch (scheme) {
210061da546Spatrick   case eManglingSchemeNone:
211061da546Spatrick     // The current mangled_name_filter would allow llvm_unreachable here.
212061da546Spatrick     return false;
213061da546Spatrick 
214061da546Spatrick   case eManglingSchemeItanium:
215061da546Spatrick     // We want the rich mangling info here, so we don't care whether or not
216061da546Spatrick     // there is a demangled string in the pool already.
217*f6aab3d8Srobert     return context.FromItaniumName(m_mangled);
218061da546Spatrick 
219061da546Spatrick   case eManglingSchemeMSVC: {
220061da546Spatrick     // We have no rich mangling for MSVC-mangled names yet, so first try to
221061da546Spatrick     // demangle it if necessary.
222061da546Spatrick     if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
223061da546Spatrick       if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) {
224*f6aab3d8Srobert         // Without the rich mangling info we have to demangle the full name.
225*f6aab3d8Srobert         // Copy it to string pool and connect the counterparts to accelerate
226*f6aab3d8Srobert         // later access in GetDemangledName().
227061da546Spatrick         m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
228061da546Spatrick                                                     m_mangled);
229061da546Spatrick         ::free(d);
230061da546Spatrick       } else {
231061da546Spatrick         m_demangled.SetCString("");
232061da546Spatrick       }
233061da546Spatrick     }
234061da546Spatrick 
235061da546Spatrick     if (m_demangled.IsEmpty()) {
236061da546Spatrick       // Cannot demangle it, so don't try parsing.
237061da546Spatrick       return false;
238061da546Spatrick     } else {
239061da546Spatrick       // Demangled successfully, we can try and parse it with
240061da546Spatrick       // CPlusPlusLanguage::MethodName.
241061da546Spatrick       return context.FromCxxMethodName(m_demangled);
242061da546Spatrick     }
243061da546Spatrick   }
244be691f3bSpatrick 
245be691f3bSpatrick   case eManglingSchemeRustV0:
246*f6aab3d8Srobert   case eManglingSchemeD:
247*f6aab3d8Srobert     // Rich demangling scheme is not supported
248be691f3bSpatrick     return false;
249061da546Spatrick   }
250061da546Spatrick   llvm_unreachable("Fully covered switch above!");
251061da546Spatrick }
252061da546Spatrick 
253061da546Spatrick // Generate the demangled name on demand using this accessor. Code in this
254061da546Spatrick // class will need to use this accessor if it wishes to decode the demangled
255061da546Spatrick // name. The result is cached and will be kept until a new string value is
256061da546Spatrick // supplied to this object, or until the end of the object's lifetime.
GetDemangledName() const257dda28197Spatrick ConstString Mangled::GetDemangledName() const {
258061da546Spatrick   // Check to make sure we have a valid mangled name and that we haven't
259061da546Spatrick   // already decoded our mangled name.
260061da546Spatrick   if (m_mangled && m_demangled.IsNull()) {
261061da546Spatrick     // Don't bother running anything that isn't mangled
262061da546Spatrick     const char *mangled_name = m_mangled.GetCString();
263*f6aab3d8Srobert     ManglingScheme mangling_scheme =
264*f6aab3d8Srobert         GetManglingScheme(m_mangled.GetStringRef());
265061da546Spatrick     if (mangling_scheme != eManglingSchemeNone &&
266061da546Spatrick         !m_mangled.GetMangledCounterpart(m_demangled)) {
267061da546Spatrick       // We didn't already mangle this name, demangle it and if all goes well
268061da546Spatrick       // add it to our map.
269061da546Spatrick       char *demangled_name = nullptr;
270061da546Spatrick       switch (mangling_scheme) {
271061da546Spatrick       case eManglingSchemeMSVC:
272061da546Spatrick         demangled_name = GetMSVCDemangledStr(mangled_name);
273061da546Spatrick         break;
274061da546Spatrick       case eManglingSchemeItanium: {
275061da546Spatrick         demangled_name = GetItaniumDemangledStr(mangled_name);
276061da546Spatrick         break;
277061da546Spatrick       }
278be691f3bSpatrick       case eManglingSchemeRustV0:
279be691f3bSpatrick         demangled_name = GetRustV0DemangledStr(mangled_name);
280be691f3bSpatrick         break;
281*f6aab3d8Srobert       case eManglingSchemeD:
282*f6aab3d8Srobert         demangled_name = GetDLangDemangledStr(mangled_name);
283*f6aab3d8Srobert         break;
284061da546Spatrick       case eManglingSchemeNone:
285061da546Spatrick         llvm_unreachable("eManglingSchemeNone was handled already");
286061da546Spatrick       }
287061da546Spatrick       if (demangled_name) {
288061da546Spatrick         m_demangled.SetStringWithMangledCounterpart(
289061da546Spatrick             llvm::StringRef(demangled_name), m_mangled);
290061da546Spatrick         free(demangled_name);
291061da546Spatrick       }
292061da546Spatrick     }
293061da546Spatrick     if (m_demangled.IsNull()) {
294061da546Spatrick       // Set the demangled string to the empty string to indicate we tried to
295061da546Spatrick       // parse it once and failed.
296061da546Spatrick       m_demangled.SetCString("");
297061da546Spatrick     }
298061da546Spatrick   }
299061da546Spatrick 
300061da546Spatrick   return m_demangled;
301061da546Spatrick }
302061da546Spatrick 
GetDisplayDemangledName() const303*f6aab3d8Srobert ConstString Mangled::GetDisplayDemangledName() const {
304dda28197Spatrick   return GetDemangledName();
305061da546Spatrick }
306061da546Spatrick 
NameMatches(const RegularExpression & regex) const307dda28197Spatrick bool Mangled::NameMatches(const RegularExpression &regex) const {
308dda28197Spatrick   if (m_mangled && regex.Execute(m_mangled.GetStringRef()))
309061da546Spatrick     return true;
310061da546Spatrick 
311dda28197Spatrick   ConstString demangled = GetDemangledName();
312dda28197Spatrick   return demangled && regex.Execute(demangled.GetStringRef());
313061da546Spatrick }
314061da546Spatrick 
315061da546Spatrick // Get the demangled name if there is one, else return the mangled name.
GetName(Mangled::NamePreference preference) const316dda28197Spatrick ConstString Mangled::GetName(Mangled::NamePreference preference) const {
317061da546Spatrick   if (preference == ePreferMangled && m_mangled)
318061da546Spatrick     return m_mangled;
319061da546Spatrick 
320*f6aab3d8Srobert   // Call the accessor to make sure we get a demangled name in case it hasn't
321*f6aab3d8Srobert   // been demangled yet...
322dda28197Spatrick   ConstString demangled = GetDemangledName();
323061da546Spatrick 
324061da546Spatrick   if (preference == ePreferDemangledWithoutArguments) {
325*f6aab3d8Srobert     if (Language *lang = Language::FindPlugin(GuessLanguage())) {
326*f6aab3d8Srobert       return lang->GetDemangledFunctionNameWithoutArguments(*this);
327*f6aab3d8Srobert     }
328061da546Spatrick   }
329061da546Spatrick   if (preference == ePreferDemangled) {
330061da546Spatrick     if (demangled)
331061da546Spatrick       return demangled;
332061da546Spatrick     return m_mangled;
333061da546Spatrick   }
334061da546Spatrick   return demangled;
335061da546Spatrick }
336061da546Spatrick 
337061da546Spatrick // Dump a Mangled object to stream "s". We don't force our demangled name to be
338061da546Spatrick // computed currently (we don't use the accessor).
Dump(Stream * s) const339061da546Spatrick void Mangled::Dump(Stream *s) const {
340061da546Spatrick   if (m_mangled) {
341061da546Spatrick     *s << ", mangled = " << m_mangled;
342061da546Spatrick   }
343061da546Spatrick   if (m_demangled) {
344061da546Spatrick     const char *demangled = m_demangled.AsCString();
345061da546Spatrick     s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
346061da546Spatrick   }
347061da546Spatrick }
348061da546Spatrick 
349061da546Spatrick // Dumps a debug version of this string with extra object and state information
350061da546Spatrick // to stream "s".
DumpDebug(Stream * s) const351061da546Spatrick void Mangled::DumpDebug(Stream *s) const {
352061da546Spatrick   s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
353061da546Spatrick             static_cast<const void *>(this));
354061da546Spatrick   m_mangled.DumpDebug(s);
355061da546Spatrick   s->Printf(", demangled = ");
356061da546Spatrick   m_demangled.DumpDebug(s);
357061da546Spatrick }
358061da546Spatrick 
359061da546Spatrick // Return the size in byte that this object takes in memory. The size includes
360061da546Spatrick // the size of the objects it owns, and not the strings that it references
361061da546Spatrick // because they are shared strings.
MemorySize() const362061da546Spatrick size_t Mangled::MemorySize() const {
363061da546Spatrick   return m_mangled.MemorySize() + m_demangled.MemorySize();
364061da546Spatrick }
365061da546Spatrick 
366061da546Spatrick // We "guess" the language because we can't determine a symbol's language from
367061da546Spatrick // it's name.  For example, a Pascal symbol can be mangled using the C++
368061da546Spatrick // Itanium scheme, and defined in a compilation unit within the same module as
369061da546Spatrick // other C++ units.  In addition, different targets could have different ways
370061da546Spatrick // of mangling names from a given language, likewise the compilation units
371061da546Spatrick // within those targets.
GuessLanguage() const372061da546Spatrick lldb::LanguageType Mangled::GuessLanguage() const {
373be691f3bSpatrick   lldb::LanguageType result = lldb::eLanguageTypeUnknown;
374be691f3bSpatrick   // Ask each language plugin to check if the mangled name belongs to it.
375be691f3bSpatrick   Language::ForEach([this, &result](Language *l) {
376be691f3bSpatrick     if (l->SymbolNameFitsToLanguage(*this)) {
377be691f3bSpatrick       result = l->GetLanguageType();
378be691f3bSpatrick       return false;
379061da546Spatrick     }
380be691f3bSpatrick     return true;
381be691f3bSpatrick   });
382be691f3bSpatrick   return result;
383061da546Spatrick }
384061da546Spatrick 
385061da546Spatrick // Dump OBJ to the supplied stream S.
operator <<(Stream & s,const Mangled & obj)386061da546Spatrick Stream &operator<<(Stream &s, const Mangled &obj) {
387061da546Spatrick   if (obj.GetMangledName())
388061da546Spatrick     s << "mangled = '" << obj.GetMangledName() << "'";
389061da546Spatrick 
390dda28197Spatrick   ConstString demangled = obj.GetDemangledName();
391061da546Spatrick   if (demangled)
392061da546Spatrick     s << ", demangled = '" << demangled << '\'';
393061da546Spatrick   else
394061da546Spatrick     s << ", demangled = <error>";
395061da546Spatrick   return s;
396061da546Spatrick }
397*f6aab3d8Srobert 
398*f6aab3d8Srobert // When encoding Mangled objects we can get away with encoding as little
399*f6aab3d8Srobert // information as is required. The enumeration below helps us to efficiently
400*f6aab3d8Srobert // encode Mangled objects.
401*f6aab3d8Srobert enum MangledEncoding {
402*f6aab3d8Srobert   /// If the Mangled object has neither a mangled name or demangled name we can
403*f6aab3d8Srobert   /// encode the object with one zero byte using the Empty enumeration.
404*f6aab3d8Srobert   Empty = 0u,
405*f6aab3d8Srobert   /// If the Mangled object has only a demangled name and no mangled named, we
406*f6aab3d8Srobert   /// can encode only the demangled name.
407*f6aab3d8Srobert   DemangledOnly = 1u,
408*f6aab3d8Srobert   /// If the mangle name can calculate the demangled name (it is the
409*f6aab3d8Srobert   /// mangled/demangled counterpart), then we only need to encode the mangled
410*f6aab3d8Srobert   /// name as the demangled name can be recomputed.
411*f6aab3d8Srobert   MangledOnly = 2u,
412*f6aab3d8Srobert   /// If we have a Mangled object with two different names that are not related
413*f6aab3d8Srobert   /// then we need to save both strings. This can happen if we have a name that
414*f6aab3d8Srobert   /// isn't a true mangled name, but we want to be able to lookup a symbol by
415*f6aab3d8Srobert   /// name and type in the symbol table. We do this for Objective C symbols like
416*f6aab3d8Srobert   /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to
417*f6aab3d8Srobert   /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to
418*f6aab3d8Srobert   /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it
419*f6aab3d8Srobert   /// would fail, but in these cases we want these unrelated names to be
420*f6aab3d8Srobert   /// preserved.
421*f6aab3d8Srobert   MangledAndDemangled = 3u
422*f6aab3d8Srobert };
423*f6aab3d8Srobert 
Decode(const DataExtractor & data,lldb::offset_t * offset_ptr,const StringTableReader & strtab)424*f6aab3d8Srobert bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
425*f6aab3d8Srobert                      const StringTableReader &strtab) {
426*f6aab3d8Srobert   m_mangled.Clear();
427*f6aab3d8Srobert   m_demangled.Clear();
428*f6aab3d8Srobert   MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr);
429*f6aab3d8Srobert   switch (encoding) {
430*f6aab3d8Srobert     case Empty:
431*f6aab3d8Srobert       return true;
432*f6aab3d8Srobert 
433*f6aab3d8Srobert     case DemangledOnly:
434*f6aab3d8Srobert       m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
435*f6aab3d8Srobert       return true;
436*f6aab3d8Srobert 
437*f6aab3d8Srobert     case MangledOnly:
438*f6aab3d8Srobert       m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
439*f6aab3d8Srobert       return true;
440*f6aab3d8Srobert 
441*f6aab3d8Srobert     case MangledAndDemangled:
442*f6aab3d8Srobert       m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
443*f6aab3d8Srobert       m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
444*f6aab3d8Srobert       return true;
445*f6aab3d8Srobert   }
446*f6aab3d8Srobert   return false;
447*f6aab3d8Srobert }
448*f6aab3d8Srobert /// The encoding format for the Mangled object is as follows:
449*f6aab3d8Srobert ///
450*f6aab3d8Srobert /// uint8_t encoding;
451*f6aab3d8Srobert /// char str1[]; (only if DemangledOnly, MangledOnly)
452*f6aab3d8Srobert /// char str2[]; (only if MangledAndDemangled)
453*f6aab3d8Srobert ///
454*f6aab3d8Srobert /// The strings are stored as NULL terminated UTF8 strings and str1 and str2
455*f6aab3d8Srobert /// are only saved if we need them based on the encoding.
456*f6aab3d8Srobert ///
457*f6aab3d8Srobert /// Some mangled names have a mangled name that can be demangled by the built
458*f6aab3d8Srobert /// in demanglers. These kinds of mangled objects know when the mangled and
459*f6aab3d8Srobert /// demangled names are the counterparts for each other. This is done because
460*f6aab3d8Srobert /// demangling is very expensive and avoiding demangling the same name twice
461*f6aab3d8Srobert /// saves us a lot of compute time. For these kinds of names we only need to
462*f6aab3d8Srobert /// save the mangled name and have the encoding set to "MangledOnly".
463*f6aab3d8Srobert ///
464*f6aab3d8Srobert /// If a mangled obejct has only a demangled name, then we save only that string
465*f6aab3d8Srobert /// and have the encoding set to "DemangledOnly".
466*f6aab3d8Srobert ///
467*f6aab3d8Srobert /// Some mangled objects have both mangled and demangled names, but the
468*f6aab3d8Srobert /// demangled name can not be computed from the mangled name. This is often used
469*f6aab3d8Srobert /// for runtime named, like Objective C runtime V2 and V3 names. Both these
470*f6aab3d8Srobert /// names must be saved and the encoding is set to "MangledAndDemangled".
471*f6aab3d8Srobert ///
472*f6aab3d8Srobert /// For a Mangled object with no names, we only need to set the encoding to
473*f6aab3d8Srobert /// "Empty" and not store any string values.
Encode(DataEncoder & file,ConstStringTable & strtab) const474*f6aab3d8Srobert void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const {
475*f6aab3d8Srobert   MangledEncoding encoding = Empty;
476*f6aab3d8Srobert   if (m_mangled) {
477*f6aab3d8Srobert     encoding = MangledOnly;
478*f6aab3d8Srobert     if (m_demangled) {
479*f6aab3d8Srobert       // We have both mangled and demangled names. If the demangled name is the
480*f6aab3d8Srobert       // counterpart of the mangled name, then we only need to save the mangled
481*f6aab3d8Srobert       // named. If they are different, we need to save both.
482*f6aab3d8Srobert       ConstString s;
483*f6aab3d8Srobert       if (!(m_mangled.GetMangledCounterpart(s) && s == m_demangled))
484*f6aab3d8Srobert         encoding = MangledAndDemangled;
485*f6aab3d8Srobert     }
486*f6aab3d8Srobert   } else if (m_demangled) {
487*f6aab3d8Srobert     encoding = DemangledOnly;
488*f6aab3d8Srobert   }
489*f6aab3d8Srobert   file.AppendU8(encoding);
490*f6aab3d8Srobert   switch (encoding) {
491*f6aab3d8Srobert     case Empty:
492*f6aab3d8Srobert       break;
493*f6aab3d8Srobert     case DemangledOnly:
494*f6aab3d8Srobert       file.AppendU32(strtab.Add(m_demangled));
495*f6aab3d8Srobert       break;
496*f6aab3d8Srobert     case MangledOnly:
497*f6aab3d8Srobert       file.AppendU32(strtab.Add(m_mangled));
498*f6aab3d8Srobert       break;
499*f6aab3d8Srobert     case MangledAndDemangled:
500*f6aab3d8Srobert       file.AppendU32(strtab.Add(m_mangled));
501*f6aab3d8Srobert       file.AppendU32(strtab.Add(m_demangled));
502*f6aab3d8Srobert       break;
503*f6aab3d8Srobert   }
504*f6aab3d8Srobert }
505