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 ®ex) 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