1cfca06d7SDimitry Andric //===-- Mangled.cpp -------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
974a628f7SDimitry Andric #include "lldb/Core/Mangled.h"
1074a628f7SDimitry Andric
1177fc4c14SDimitry Andric #include "lldb/Core/DataFileCache.h"
1294994d37SDimitry Andric #include "lldb/Core/RichManglingContext.h"
13c0981da4SDimitry Andric #include "lldb/Target/Language.h"
1474a628f7SDimitry Andric #include "lldb/Utility/ConstString.h"
1577fc4c14SDimitry Andric #include "lldb/Utility/DataEncoder.h"
16145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
1774a628f7SDimitry Andric #include "lldb/Utility/Log.h"
1874a628f7SDimitry Andric #include "lldb/Utility/RegularExpression.h"
1974a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
20f73363f1SDimitry Andric #include "lldb/lldb-enumerations.h"
21f034231aSEd Maste
22ac9a064cSDimitry Andric #include "llvm/ADT/StringExtras.h"
23f73363f1SDimitry Andric #include "llvm/ADT/StringRef.h"
24f73363f1SDimitry Andric #include "llvm/Demangle/Demangle.h"
25f73363f1SDimitry Andric #include "llvm/Support/Compiler.h"
2674a628f7SDimitry Andric
27f73363f1SDimitry Andric #include <mutex>
28f73363f1SDimitry Andric #include <string>
297fa27ce4SDimitry Andric #include <string_view>
30f73363f1SDimitry Andric #include <utility>
3174a628f7SDimitry Andric
32344a3780SDimitry Andric #include <cstdlib>
33344a3780SDimitry Andric #include <cstring>
34f034231aSEd Maste using namespace lldb_private;
35f034231aSEd Maste
cstring_is_mangled(llvm::StringRef s)36706b4fc4SDimitry Andric static inline bool cstring_is_mangled(llvm::StringRef s) {
37706b4fc4SDimitry Andric return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
38f034231aSEd Maste }
39f034231aSEd Maste
40f034231aSEd Maste #pragma mark Mangled
4114f1b3e8SDimitry Andric
GetManglingScheme(llvm::StringRef const name)42706b4fc4SDimitry Andric Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
43706b4fc4SDimitry Andric if (name.empty())
44706b4fc4SDimitry Andric return Mangled::eManglingSchemeNone;
45706b4fc4SDimitry Andric
46312c0ed1SDimitry Andric if (name.starts_with("?"))
47706b4fc4SDimitry Andric return Mangled::eManglingSchemeMSVC;
48706b4fc4SDimitry Andric
49312c0ed1SDimitry Andric if (name.starts_with("_R"))
50344a3780SDimitry Andric return Mangled::eManglingSchemeRustV0;
51344a3780SDimitry Andric
52ac9a064cSDimitry Andric if (name.starts_with("_D")) {
53ac9a064cSDimitry Andric // A dlang mangled name begins with `_D`, followed by a numeric length. One
54ac9a064cSDimitry Andric // known exception is the symbol `_Dmain`.
55ac9a064cSDimitry Andric // See `SymbolName` and `LName` in
56ac9a064cSDimitry Andric // https://dlang.org/spec/abi.html#name_mangling
57ac9a064cSDimitry Andric llvm::StringRef buf = name.drop_front(2);
58ac9a064cSDimitry Andric if (!buf.empty() && (llvm::isDigit(buf.front()) || name == "_Dmain"))
59c0981da4SDimitry Andric return Mangled::eManglingSchemeD;
60ac9a064cSDimitry Andric }
61c0981da4SDimitry Andric
62312c0ed1SDimitry Andric if (name.starts_with("_Z"))
63706b4fc4SDimitry Andric return Mangled::eManglingSchemeItanium;
64706b4fc4SDimitry Andric
65706b4fc4SDimitry Andric // ___Z is a clang extension of block invocations
66312c0ed1SDimitry Andric if (name.starts_with("___Z"))
67706b4fc4SDimitry Andric return Mangled::eManglingSchemeItanium;
68706b4fc4SDimitry Andric
69b1c73532SDimitry Andric // Swift's older style of mangling used "_T" as a mangling prefix. This can
70b1c73532SDimitry Andric // lead to false positives with other symbols that just so happen to start
71b1c73532SDimitry Andric // with "_T". To minimize the chance of that happening, we only return true
72b1c73532SDimitry Andric // for select old-style swift mangled names. The known cases are ObjC classes
73b1c73532SDimitry Andric // and protocols. Classes are either prefixed with "_TtC" or "_TtGC".
74b1c73532SDimitry Andric // Protocols are prefixed with "_TtP".
75312c0ed1SDimitry Andric if (name.starts_with("_TtC") || name.starts_with("_TtGC") ||
76312c0ed1SDimitry Andric name.starts_with("_TtP"))
77b1c73532SDimitry Andric return Mangled::eManglingSchemeSwift;
78b1c73532SDimitry Andric
79b1c73532SDimitry Andric // Swift 4.2 used "$S" and "_$S".
80b1c73532SDimitry Andric // Swift 5 and onward uses "$s" and "_$s".
81b1c73532SDimitry Andric // Swift also uses "@__swiftmacro_" as a prefix for mangling filenames.
82312c0ed1SDimitry Andric if (name.starts_with("$S") || name.starts_with("_$S") ||
83312c0ed1SDimitry Andric name.starts_with("$s") || name.starts_with("_$s") ||
84312c0ed1SDimitry Andric name.starts_with("@__swiftmacro_"))
85b1c73532SDimitry Andric return Mangled::eManglingSchemeSwift;
86b1c73532SDimitry Andric
87706b4fc4SDimitry Andric return Mangled::eManglingSchemeNone;
88706b4fc4SDimitry Andric }
89706b4fc4SDimitry Andric
Mangled(ConstString s)905f29bb8aSDimitry Andric Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
91f034231aSEd Maste if (s)
92f034231aSEd Maste SetValue(s);
93f034231aSEd Maste }
94f034231aSEd Maste
Mangled(llvm::StringRef name)9514f1b3e8SDimitry Andric Mangled::Mangled(llvm::StringRef name) {
9614f1b3e8SDimitry Andric if (!name.empty())
9714f1b3e8SDimitry Andric SetValue(ConstString(name));
9814f1b3e8SDimitry Andric }
9914f1b3e8SDimitry Andric
1006f8fc217SDimitry Andric // Convert to bool operator. This allows code to check any Mangled objects
101f73363f1SDimitry Andric // to see if they contain anything valid using code such as:
102f034231aSEd Maste //
103f034231aSEd Maste // Mangled mangled(...);
104f034231aSEd Maste // if (mangled)
105f034231aSEd Maste // { ...
operator bool() const1066f8fc217SDimitry Andric Mangled::operator bool() const { return m_mangled || m_demangled; }
107f034231aSEd Maste
108f034231aSEd Maste // Clear the mangled and demangled values.
Clear()10914f1b3e8SDimitry Andric void Mangled::Clear() {
110f034231aSEd Maste m_mangled.Clear();
111f034231aSEd Maste m_demangled.Clear();
112f034231aSEd Maste }
113f034231aSEd Maste
1145e95aa85SEd Maste // Compare the string values.
Compare(const Mangled & a,const Mangled & b)11514f1b3e8SDimitry Andric int Mangled::Compare(const Mangled &a, const Mangled &b) {
116cfca06d7SDimitry Andric return ConstString::Compare(a.GetName(ePreferMangled),
117cfca06d7SDimitry Andric b.GetName(ePreferMangled));
118f034231aSEd Maste }
119f034231aSEd Maste
SetValue(ConstString name)1205f29bb8aSDimitry Andric void Mangled::SetValue(ConstString name) {
12114f1b3e8SDimitry Andric if (name) {
122706b4fc4SDimitry Andric if (cstring_is_mangled(name.GetStringRef())) {
123f034231aSEd Maste m_demangled.Clear();
124f034231aSEd Maste m_mangled = name;
12514f1b3e8SDimitry Andric } else {
126f034231aSEd Maste m_demangled = name;
127f034231aSEd Maste m_mangled.Clear();
128f034231aSEd Maste }
12914f1b3e8SDimitry Andric } else {
130f034231aSEd Maste m_demangled.Clear();
131f034231aSEd Maste m_mangled.Clear();
132f034231aSEd Maste }
133f034231aSEd Maste }
134f034231aSEd Maste
13594994d37SDimitry Andric // Local helpers for different demangling implementations.
GetMSVCDemangledStr(llvm::StringRef M)136ac9a064cSDimitry Andric static char *GetMSVCDemangledStr(llvm::StringRef M) {
137ead24645SDimitry Andric char *demangled_cstr = llvm::microsoftDemangle(
1387fa27ce4SDimitry Andric M, nullptr, nullptr,
139c0981da4SDimitry Andric llvm::MSDemangleFlags(
140c0981da4SDimitry Andric llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention |
141c0981da4SDimitry Andric llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType));
14294994d37SDimitry Andric
143145449b1SDimitry Andric if (Log *log = GetLog(LLDBLog::Demangle)) {
14494994d37SDimitry Andric if (demangled_cstr && demangled_cstr[0])
1457fa27ce4SDimitry Andric LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M.data(), demangled_cstr);
14694994d37SDimitry Andric else
1477fa27ce4SDimitry Andric LLDB_LOGF(log, "demangled msvc: %s -> error", M.data());
14894994d37SDimitry Andric }
14994994d37SDimitry Andric
15094994d37SDimitry Andric return demangled_cstr;
15194994d37SDimitry Andric }
15294994d37SDimitry Andric
GetItaniumDemangledStr(const char * M)15394994d37SDimitry Andric static char *GetItaniumDemangledStr(const char *M) {
15494994d37SDimitry Andric char *demangled_cstr = nullptr;
15594994d37SDimitry Andric
15694994d37SDimitry Andric llvm::ItaniumPartialDemangler ipd;
15794994d37SDimitry Andric bool err = ipd.partialDemangle(M);
15894994d37SDimitry Andric if (!err) {
15994994d37SDimitry Andric // Default buffer and size (will realloc in case it's too small).
16094994d37SDimitry Andric size_t demangled_size = 80;
16194994d37SDimitry Andric demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
16294994d37SDimitry Andric demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
16394994d37SDimitry Andric
16494994d37SDimitry Andric assert(demangled_cstr &&
16594994d37SDimitry Andric "finishDemangle must always succeed if partialDemangle did");
16694994d37SDimitry Andric assert(demangled_cstr[demangled_size - 1] == '\0' &&
16794994d37SDimitry Andric "Expected demangled_size to return length including trailing null");
16894994d37SDimitry Andric }
16994994d37SDimitry Andric
170145449b1SDimitry Andric if (Log *log = GetLog(LLDBLog::Demangle)) {
17194994d37SDimitry Andric if (demangled_cstr)
172ead24645SDimitry Andric LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
17394994d37SDimitry Andric else
174ead24645SDimitry Andric LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
17594994d37SDimitry Andric }
17694994d37SDimitry Andric
17794994d37SDimitry Andric return demangled_cstr;
17894994d37SDimitry Andric }
17994994d37SDimitry Andric
GetRustV0DemangledStr(llvm::StringRef M)180ac9a064cSDimitry Andric static char *GetRustV0DemangledStr(llvm::StringRef M) {
181145449b1SDimitry Andric char *demangled_cstr = llvm::rustDemangle(M);
182344a3780SDimitry Andric
183145449b1SDimitry Andric if (Log *log = GetLog(LLDBLog::Demangle)) {
184344a3780SDimitry Andric if (demangled_cstr && demangled_cstr[0])
185344a3780SDimitry Andric LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr);
186344a3780SDimitry Andric else
187ac9a064cSDimitry Andric LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle",
188ac9a064cSDimitry Andric static_cast<std::string_view>(M));
189344a3780SDimitry Andric }
190344a3780SDimitry Andric
191344a3780SDimitry Andric return demangled_cstr;
192344a3780SDimitry Andric }
193344a3780SDimitry Andric
GetDLangDemangledStr(llvm::StringRef M)194ac9a064cSDimitry Andric static char *GetDLangDemangledStr(llvm::StringRef M) {
195c0981da4SDimitry Andric char *demangled_cstr = llvm::dlangDemangle(M);
196c0981da4SDimitry Andric
197145449b1SDimitry Andric if (Log *log = GetLog(LLDBLog::Demangle)) {
198c0981da4SDimitry Andric if (demangled_cstr && demangled_cstr[0])
199c0981da4SDimitry Andric LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr);
200c0981da4SDimitry Andric else
201ac9a064cSDimitry Andric LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle",
202ac9a064cSDimitry Andric static_cast<std::string_view>(M));
203c0981da4SDimitry Andric }
204c0981da4SDimitry Andric
205c0981da4SDimitry Andric return demangled_cstr;
206c0981da4SDimitry Andric }
207c0981da4SDimitry Andric
20894994d37SDimitry Andric // Explicit demangling for scheduled requests during batch processing. This
20994994d37SDimitry Andric // makes use of ItaniumPartialDemangler's rich demangle info
GetRichManglingInfo(RichManglingContext & context,SkipMangledNameFn * skip_mangled_name)210145449b1SDimitry Andric bool Mangled::GetRichManglingInfo(RichManglingContext &context,
211145449b1SDimitry Andric SkipMangledNameFn *skip_mangled_name) {
21294994d37SDimitry Andric // Others are not meant to arrive here. ObjC names or C's main() for example
21394994d37SDimitry Andric // have their names stored in m_demangled, while m_mangled is empty.
21494994d37SDimitry Andric assert(m_mangled);
21594994d37SDimitry Andric
21694994d37SDimitry Andric // Check whether or not we are interested in this name at all.
217706b4fc4SDimitry Andric ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef());
21894994d37SDimitry Andric if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
21994994d37SDimitry Andric return false;
22094994d37SDimitry Andric
22194994d37SDimitry Andric switch (scheme) {
22294994d37SDimitry Andric case eManglingSchemeNone:
22394994d37SDimitry Andric // The current mangled_name_filter would allow llvm_unreachable here.
22494994d37SDimitry Andric return false;
22594994d37SDimitry Andric
22694994d37SDimitry Andric case eManglingSchemeItanium:
22794994d37SDimitry Andric // We want the rich mangling info here, so we don't care whether or not
22894994d37SDimitry Andric // there is a demangled string in the pool already.
229145449b1SDimitry Andric return context.FromItaniumName(m_mangled);
23094994d37SDimitry Andric
23194994d37SDimitry Andric case eManglingSchemeMSVC: {
23294994d37SDimitry Andric // We have no rich mangling for MSVC-mangled names yet, so first try to
23394994d37SDimitry Andric // demangle it if necessary.
23494994d37SDimitry Andric if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
2357fa27ce4SDimitry Andric if (char *d = GetMSVCDemangledStr(m_mangled)) {
236145449b1SDimitry Andric // Without the rich mangling info we have to demangle the full name.
237145449b1SDimitry Andric // Copy it to string pool and connect the counterparts to accelerate
238145449b1SDimitry Andric // later access in GetDemangledName().
23994994d37SDimitry Andric m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
24094994d37SDimitry Andric m_mangled);
24194994d37SDimitry Andric ::free(d);
24294994d37SDimitry Andric } else {
24394994d37SDimitry Andric m_demangled.SetCString("");
24494994d37SDimitry Andric }
24594994d37SDimitry Andric }
24694994d37SDimitry Andric
24794994d37SDimitry Andric if (m_demangled.IsEmpty()) {
24894994d37SDimitry Andric // Cannot demangle it, so don't try parsing.
24994994d37SDimitry Andric return false;
25094994d37SDimitry Andric } else {
25194994d37SDimitry Andric // Demangled successfully, we can try and parse it with
25294994d37SDimitry Andric // CPlusPlusLanguage::MethodName.
25394994d37SDimitry Andric return context.FromCxxMethodName(m_demangled);
25494994d37SDimitry Andric }
25594994d37SDimitry Andric }
256344a3780SDimitry Andric
257344a3780SDimitry Andric case eManglingSchemeRustV0:
258c0981da4SDimitry Andric case eManglingSchemeD:
259b1c73532SDimitry Andric case eManglingSchemeSwift:
260c0981da4SDimitry Andric // Rich demangling scheme is not supported
261344a3780SDimitry Andric return false;
26294994d37SDimitry Andric }
26394994d37SDimitry Andric llvm_unreachable("Fully covered switch above!");
26494994d37SDimitry Andric }
26594994d37SDimitry Andric
266f73363f1SDimitry Andric // Generate the demangled name on demand using this accessor. Code in this
267f73363f1SDimitry Andric // class will need to use this accessor if it wishes to decode the demangled
268f73363f1SDimitry Andric // name. The result is cached and will be kept until a new string value is
269f73363f1SDimitry Andric // supplied to this object, or until the end of the object's lifetime.
GetDemangledName() const270cfca06d7SDimitry Andric ConstString Mangled::GetDemangledName() const {
271f73363f1SDimitry Andric // Check to make sure we have a valid mangled name and that we haven't
272f73363f1SDimitry Andric // already decoded our mangled name.
27394994d37SDimitry Andric if (m_mangled && m_demangled.IsNull()) {
274f034231aSEd Maste // Don't bother running anything that isn't mangled
2755e95aa85SEd Maste const char *mangled_name = m_mangled.GetCString();
276c0981da4SDimitry Andric ManglingScheme mangling_scheme =
277c0981da4SDimitry Andric GetManglingScheme(m_mangled.GetStringRef());
2785e95aa85SEd Maste if (mangling_scheme != eManglingSchemeNone &&
27914f1b3e8SDimitry Andric !m_mangled.GetMangledCounterpart(m_demangled)) {
280f034231aSEd Maste // We didn't already mangle this name, demangle it and if all goes well
281f034231aSEd Maste // add it to our map.
2825e95aa85SEd Maste char *demangled_name = nullptr;
28314f1b3e8SDimitry Andric switch (mangling_scheme) {
28494994d37SDimitry Andric case eManglingSchemeMSVC:
28594994d37SDimitry Andric demangled_name = GetMSVCDemangledStr(mangled_name);
2865e95aa85SEd Maste break;
28714f1b3e8SDimitry Andric case eManglingSchemeItanium: {
28894994d37SDimitry Andric demangled_name = GetItaniumDemangledStr(mangled_name);
2895e95aa85SEd Maste break;
2905e95aa85SEd Maste }
291344a3780SDimitry Andric case eManglingSchemeRustV0:
2927fa27ce4SDimitry Andric demangled_name = GetRustV0DemangledStr(m_mangled);
293344a3780SDimitry Andric break;
294c0981da4SDimitry Andric case eManglingSchemeD:
2957fa27ce4SDimitry Andric demangled_name = GetDLangDemangledStr(m_mangled);
296c0981da4SDimitry Andric break;
297b1c73532SDimitry Andric case eManglingSchemeSwift:
298b1c73532SDimitry Andric // Demangling a swift name requires the swift compiler. This is
299b1c73532SDimitry Andric // explicitly unsupported on llvm.org.
300b1c73532SDimitry Andric break;
3015e95aa85SEd Maste case eManglingSchemeNone:
30294994d37SDimitry Andric llvm_unreachable("eManglingSchemeNone was handled already");
3035e95aa85SEd Maste }
30414f1b3e8SDimitry Andric if (demangled_name) {
30594994d37SDimitry Andric m_demangled.SetStringWithMangledCounterpart(
30694994d37SDimitry Andric llvm::StringRef(demangled_name), m_mangled);
307f034231aSEd Maste free(demangled_name);
308f034231aSEd Maste }
309f034231aSEd Maste }
31094994d37SDimitry Andric if (m_demangled.IsNull()) {
311f73363f1SDimitry Andric // Set the demangled string to the empty string to indicate we tried to
312f73363f1SDimitry Andric // parse it once and failed.
313f034231aSEd Maste m_demangled.SetCString("");
314f034231aSEd Maste }
315f034231aSEd Maste }
316f034231aSEd Maste
317f034231aSEd Maste return m_demangled;
318f034231aSEd Maste }
319f034231aSEd Maste
GetDisplayDemangledName() const320c0981da4SDimitry Andric ConstString Mangled::GetDisplayDemangledName() const {
321ac9a064cSDimitry Andric if (Language *lang = Language::FindPlugin(GuessLanguage()))
322ac9a064cSDimitry Andric return lang->GetDisplayDemangledName(*this);
323cfca06d7SDimitry Andric return GetDemangledName();
324027f1c96SDimitry Andric }
325027f1c96SDimitry Andric
NameMatches(const RegularExpression & regex) const326cfca06d7SDimitry Andric bool Mangled::NameMatches(const RegularExpression ®ex) const {
327cfca06d7SDimitry Andric if (m_mangled && regex.Execute(m_mangled.GetStringRef()))
328f034231aSEd Maste return true;
329f034231aSEd Maste
330cfca06d7SDimitry Andric ConstString demangled = GetDemangledName();
331cfca06d7SDimitry Andric return demangled && regex.Execute(demangled.GetStringRef());
332f034231aSEd Maste }
333f034231aSEd Maste
334f034231aSEd Maste // Get the demangled name if there is one, else return the mangled name.
GetName(Mangled::NamePreference preference) const335cfca06d7SDimitry Andric ConstString Mangled::GetName(Mangled::NamePreference preference) const {
336e81d9d49SDimitry Andric if (preference == ePreferMangled && m_mangled)
337e81d9d49SDimitry Andric return m_mangled;
338e81d9d49SDimitry Andric
339c0981da4SDimitry Andric // Call the accessor to make sure we get a demangled name in case it hasn't
340c0981da4SDimitry Andric // been demangled yet...
341cfca06d7SDimitry Andric ConstString demangled = GetDemangledName();
342027f1c96SDimitry Andric
34314f1b3e8SDimitry Andric if (preference == ePreferDemangledWithoutArguments) {
344c0981da4SDimitry Andric if (Language *lang = Language::FindPlugin(GuessLanguage())) {
345c0981da4SDimitry Andric return lang->GetDemangledFunctionNameWithoutArguments(*this);
346c0981da4SDimitry Andric }
347205afe67SEd Maste }
34814f1b3e8SDimitry Andric if (preference == ePreferDemangled) {
349027f1c96SDimitry Andric if (demangled)
350027f1c96SDimitry Andric return demangled;
351f034231aSEd Maste return m_mangled;
352f034231aSEd Maste }
353027f1c96SDimitry Andric return demangled;
354f034231aSEd Maste }
355f034231aSEd Maste
356f73363f1SDimitry Andric // Dump a Mangled object to stream "s". We don't force our demangled name to be
357f73363f1SDimitry Andric // computed currently (we don't use the accessor).
Dump(Stream * s) const35814f1b3e8SDimitry Andric void Mangled::Dump(Stream *s) const {
35914f1b3e8SDimitry Andric if (m_mangled) {
360f034231aSEd Maste *s << ", mangled = " << m_mangled;
361f034231aSEd Maste }
36214f1b3e8SDimitry Andric if (m_demangled) {
363f034231aSEd Maste const char *demangled = m_demangled.AsCString();
364f034231aSEd Maste s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
365f034231aSEd Maste }
366f034231aSEd Maste }
367f034231aSEd Maste
368f73363f1SDimitry Andric // Dumps a debug version of this string with extra object and state information
369f73363f1SDimitry Andric // to stream "s".
DumpDebug(Stream * s) const37014f1b3e8SDimitry Andric void Mangled::DumpDebug(Stream *s) const {
3710cac4ca3SEd Maste s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
3720cac4ca3SEd Maste static_cast<const void *>(this));
373f034231aSEd Maste m_mangled.DumpDebug(s);
374f034231aSEd Maste s->Printf(", demangled = ");
375f034231aSEd Maste m_demangled.DumpDebug(s);
376f034231aSEd Maste }
377f034231aSEd Maste
378f73363f1SDimitry Andric // Return the size in byte that this object takes in memory. The size includes
379f73363f1SDimitry Andric // the size of the objects it owns, and not the strings that it references
380f73363f1SDimitry Andric // because they are shared strings.
MemorySize() const38114f1b3e8SDimitry Andric size_t Mangled::MemorySize() const {
382f034231aSEd Maste return m_mangled.MemorySize() + m_demangled.MemorySize();
383f034231aSEd Maste }
384f034231aSEd Maste
385f73363f1SDimitry Andric // We "guess" the language because we can't determine a symbol's language from
386f73363f1SDimitry Andric // it's name. For example, a Pascal symbol can be mangled using the C++
387f73363f1SDimitry Andric // Itanium scheme, and defined in a compilation unit within the same module as
388f73363f1SDimitry Andric // other C++ units. In addition, different targets could have different ways
389f73363f1SDimitry Andric // of mangling names from a given language, likewise the compilation units
390f73363f1SDimitry Andric // within those targets.
GuessLanguage() const39114f1b3e8SDimitry Andric lldb::LanguageType Mangled::GuessLanguage() const {
392344a3780SDimitry Andric lldb::LanguageType result = lldb::eLanguageTypeUnknown;
393344a3780SDimitry Andric // Ask each language plugin to check if the mangled name belongs to it.
394344a3780SDimitry Andric Language::ForEach([this, &result](Language *l) {
395344a3780SDimitry Andric if (l->SymbolNameFitsToLanguage(*this)) {
396344a3780SDimitry Andric result = l->GetLanguageType();
397344a3780SDimitry Andric return false;
39812bd4897SEd Maste }
399344a3780SDimitry Andric return true;
400344a3780SDimitry Andric });
401344a3780SDimitry Andric return result;
40212bd4897SEd Maste }
40312bd4897SEd Maste
404f034231aSEd Maste // Dump OBJ to the supplied stream S.
operator <<(Stream & s,const Mangled & obj)40514f1b3e8SDimitry Andric Stream &operator<<(Stream &s, const Mangled &obj) {
406f034231aSEd Maste if (obj.GetMangledName())
407f034231aSEd Maste s << "mangled = '" << obj.GetMangledName() << "'";
408f034231aSEd Maste
409cfca06d7SDimitry Andric ConstString demangled = obj.GetDemangledName();
410f034231aSEd Maste if (demangled)
411f034231aSEd Maste s << ", demangled = '" << demangled << '\'';
412f034231aSEd Maste else
413f034231aSEd Maste s << ", demangled = <error>";
414f034231aSEd Maste return s;
415f034231aSEd Maste }
41677fc4c14SDimitry Andric
41777fc4c14SDimitry Andric // When encoding Mangled objects we can get away with encoding as little
41877fc4c14SDimitry Andric // information as is required. The enumeration below helps us to efficiently
41977fc4c14SDimitry Andric // encode Mangled objects.
42077fc4c14SDimitry Andric enum MangledEncoding {
42177fc4c14SDimitry Andric /// If the Mangled object has neither a mangled name or demangled name we can
42277fc4c14SDimitry Andric /// encode the object with one zero byte using the Empty enumeration.
42377fc4c14SDimitry Andric Empty = 0u,
42477fc4c14SDimitry Andric /// If the Mangled object has only a demangled name and no mangled named, we
42577fc4c14SDimitry Andric /// can encode only the demangled name.
42677fc4c14SDimitry Andric DemangledOnly = 1u,
42777fc4c14SDimitry Andric /// If the mangle name can calculate the demangled name (it is the
42877fc4c14SDimitry Andric /// mangled/demangled counterpart), then we only need to encode the mangled
42977fc4c14SDimitry Andric /// name as the demangled name can be recomputed.
43077fc4c14SDimitry Andric MangledOnly = 2u,
43177fc4c14SDimitry Andric /// If we have a Mangled object with two different names that are not related
43277fc4c14SDimitry Andric /// then we need to save both strings. This can happen if we have a name that
43377fc4c14SDimitry Andric /// isn't a true mangled name, but we want to be able to lookup a symbol by
43477fc4c14SDimitry Andric /// name and type in the symbol table. We do this for Objective C symbols like
43577fc4c14SDimitry Andric /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to
43677fc4c14SDimitry Andric /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to
43777fc4c14SDimitry Andric /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it
43877fc4c14SDimitry Andric /// would fail, but in these cases we want these unrelated names to be
43977fc4c14SDimitry Andric /// preserved.
44077fc4c14SDimitry Andric MangledAndDemangled = 3u
44177fc4c14SDimitry Andric };
44277fc4c14SDimitry Andric
Decode(const DataExtractor & data,lldb::offset_t * offset_ptr,const StringTableReader & strtab)44377fc4c14SDimitry Andric bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
44477fc4c14SDimitry Andric const StringTableReader &strtab) {
44577fc4c14SDimitry Andric m_mangled.Clear();
44677fc4c14SDimitry Andric m_demangled.Clear();
44777fc4c14SDimitry Andric MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr);
44877fc4c14SDimitry Andric switch (encoding) {
44977fc4c14SDimitry Andric case Empty:
45077fc4c14SDimitry Andric return true;
45177fc4c14SDimitry Andric
45277fc4c14SDimitry Andric case DemangledOnly:
45377fc4c14SDimitry Andric m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
45477fc4c14SDimitry Andric return true;
45577fc4c14SDimitry Andric
45677fc4c14SDimitry Andric case MangledOnly:
45777fc4c14SDimitry Andric m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
45877fc4c14SDimitry Andric return true;
45977fc4c14SDimitry Andric
46077fc4c14SDimitry Andric case MangledAndDemangled:
46177fc4c14SDimitry Andric m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
46277fc4c14SDimitry Andric m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
46377fc4c14SDimitry Andric return true;
46477fc4c14SDimitry Andric }
46577fc4c14SDimitry Andric return false;
46677fc4c14SDimitry Andric }
46777fc4c14SDimitry Andric /// The encoding format for the Mangled object is as follows:
46877fc4c14SDimitry Andric ///
46977fc4c14SDimitry Andric /// uint8_t encoding;
47077fc4c14SDimitry Andric /// char str1[]; (only if DemangledOnly, MangledOnly)
47177fc4c14SDimitry Andric /// char str2[]; (only if MangledAndDemangled)
47277fc4c14SDimitry Andric ///
47377fc4c14SDimitry Andric /// The strings are stored as NULL terminated UTF8 strings and str1 and str2
47477fc4c14SDimitry Andric /// are only saved if we need them based on the encoding.
47577fc4c14SDimitry Andric ///
47677fc4c14SDimitry Andric /// Some mangled names have a mangled name that can be demangled by the built
47777fc4c14SDimitry Andric /// in demanglers. These kinds of mangled objects know when the mangled and
47877fc4c14SDimitry Andric /// demangled names are the counterparts for each other. This is done because
47977fc4c14SDimitry Andric /// demangling is very expensive and avoiding demangling the same name twice
48077fc4c14SDimitry Andric /// saves us a lot of compute time. For these kinds of names we only need to
48177fc4c14SDimitry Andric /// save the mangled name and have the encoding set to "MangledOnly".
48277fc4c14SDimitry Andric ///
48377fc4c14SDimitry Andric /// If a mangled obejct has only a demangled name, then we save only that string
48477fc4c14SDimitry Andric /// and have the encoding set to "DemangledOnly".
48577fc4c14SDimitry Andric ///
48677fc4c14SDimitry Andric /// Some mangled objects have both mangled and demangled names, but the
48777fc4c14SDimitry Andric /// demangled name can not be computed from the mangled name. This is often used
48877fc4c14SDimitry Andric /// for runtime named, like Objective C runtime V2 and V3 names. Both these
48977fc4c14SDimitry Andric /// names must be saved and the encoding is set to "MangledAndDemangled".
49077fc4c14SDimitry Andric ///
49177fc4c14SDimitry Andric /// For a Mangled object with no names, we only need to set the encoding to
49277fc4c14SDimitry Andric /// "Empty" and not store any string values.
Encode(DataEncoder & file,ConstStringTable & strtab) const49377fc4c14SDimitry Andric void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const {
49477fc4c14SDimitry Andric MangledEncoding encoding = Empty;
49577fc4c14SDimitry Andric if (m_mangled) {
49677fc4c14SDimitry Andric encoding = MangledOnly;
49777fc4c14SDimitry Andric if (m_demangled) {
49877fc4c14SDimitry Andric // We have both mangled and demangled names. If the demangled name is the
49977fc4c14SDimitry Andric // counterpart of the mangled name, then we only need to save the mangled
50077fc4c14SDimitry Andric // named. If they are different, we need to save both.
50177fc4c14SDimitry Andric ConstString s;
50277fc4c14SDimitry Andric if (!(m_mangled.GetMangledCounterpart(s) && s == m_demangled))
50377fc4c14SDimitry Andric encoding = MangledAndDemangled;
50477fc4c14SDimitry Andric }
50577fc4c14SDimitry Andric } else if (m_demangled) {
50677fc4c14SDimitry Andric encoding = DemangledOnly;
50777fc4c14SDimitry Andric }
50877fc4c14SDimitry Andric file.AppendU8(encoding);
50977fc4c14SDimitry Andric switch (encoding) {
51077fc4c14SDimitry Andric case Empty:
51177fc4c14SDimitry Andric break;
51277fc4c14SDimitry Andric case DemangledOnly:
51377fc4c14SDimitry Andric file.AppendU32(strtab.Add(m_demangled));
51477fc4c14SDimitry Andric break;
51577fc4c14SDimitry Andric case MangledOnly:
51677fc4c14SDimitry Andric file.AppendU32(strtab.Add(m_mangled));
51777fc4c14SDimitry Andric break;
51877fc4c14SDimitry Andric case MangledAndDemangled:
51977fc4c14SDimitry Andric file.AppendU32(strtab.Add(m_mangled));
52077fc4c14SDimitry Andric file.AppendU32(strtab.Add(m_demangled));
52177fc4c14SDimitry Andric break;
52277fc4c14SDimitry Andric }
52377fc4c14SDimitry Andric }
524