Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/Mangled.cpp
Line
Count
Source (jump to first uncovered line)
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/DataFileCache.h"
12
#include "lldb/Core/RichManglingContext.h"
13
#include "lldb/Target/Language.h"
14
#include "lldb/Utility/ConstString.h"
15
#include "lldb/Utility/DataEncoder.h"
16
#include "lldb/Utility/LLDBLog.h"
17
#include "lldb/Utility/Log.h"
18
#include "lldb/Utility/RegularExpression.h"
19
#include "lldb/Utility/Stream.h"
20
#include "lldb/lldb-enumerations.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 <string_view>
29
#include <utility>
30
31
#include <cstdlib>
32
#include <cstring>
33
using namespace lldb_private;
34
35
123M
static inline bool cstring_is_mangled(llvm::StringRef s) {
36
123M
  return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
37
123M
}
38
39
#pragma mark Mangled
40
41
158M
Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
42
158M
  if (name.empty())
43
59
    return Mangled::eManglingSchemeNone;
44
45
158M
  if (name.startswith("?"))
46
0
    return Mangled::eManglingSchemeMSVC;
47
48
158M
  if (name.startswith("_R"))
49
13.0k
    return Mangled::eManglingSchemeRustV0;
50
51
158M
  if (name.startswith("_D"))
52
138k
    return Mangled::eManglingSchemeD;
53
54
158M
  if (name.startswith("_Z"))
55
62.5M
    return Mangled::eManglingSchemeItanium;
56
57
  // ___Z is a clang extension of block invocations
58
95.6M
  if (name.startswith("___Z"))
59
4.34M
    return Mangled::eManglingSchemeItanium;
60
61
  // Swift's older style of mangling used "_T" as a mangling prefix. This can
62
  // lead to false positives with other symbols that just so happen to start
63
  // with "_T". To minimize the chance of that happening, we only return true
64
  // for select old-style swift mangled names. The known cases are ObjC classes
65
  // and protocols. Classes are either prefixed with "_TtC" or "_TtGC".
66
  // Protocols are prefixed with "_TtP".
67
91.3M
  if (name.startswith("_TtC") || 
name.startswith("_TtGC")91.3M
||
68
91.3M
      
name.startswith("_TtP")91.3M
)
69
2
    return Mangled::eManglingSchemeSwift;
70
71
  // Swift 4.2 used "$S" and "_$S".
72
  // Swift 5 and onward uses "$s" and "_$s".
73
  // Swift also uses "@__swiftmacro_" as a prefix for mangling filenames.
74
91.3M
  if (name.startswith("$S") || 
name.startswith("_$S")91.3M
||
75
91.3M
      
name.startswith("$s")91.3M
||
name.startswith("_$s")91.2M
||
76
91.3M
      
name.startswith("@__swiftmacro_")91.2M
)
77
73.8k
    return Mangled::eManglingSchemeSwift;
78
79
91.2M
  return Mangled::eManglingSchemeNone;
80
91.3M
}
81
82
110k
Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
83
110k
  if (s)
84
93.0k
    SetValue(s);
85
110k
}
86
87
7.80k
Mangled::Mangled(llvm::StringRef name) {
88
7.80k
  if (!name.empty())
89
6.21k
    SetValue(ConstString(name));
90
7.80k
}
91
92
// Convert to bool operator. This allows code to check any Mangled objects
93
// to see if they contain anything valid using code such as:
94
//
95
//  Mangled mangled(...);
96
//  if (mangled)
97
//  { ...
98
9.72M
Mangled::operator bool() const { return m_mangled || 
m_demangled9.72M
; }
99
100
// Clear the mangled and demangled values.
101
270k
void Mangled::Clear() {
102
270k
  m_mangled.Clear();
103
270k
  m_demangled.Clear();
104
270k
}
105
106
// Compare the string values.
107
0
int Mangled::Compare(const Mangled &a, const Mangled &b) {
108
0
  return ConstString::Compare(a.GetName(ePreferMangled),
109
0
                              b.GetName(ePreferMangled));
110
0
}
111
112
123M
void Mangled::SetValue(ConstString name) {
113
123M
  if (name) {
114
123M
    if (cstring_is_mangled(name.GetStringRef())) {
115
32.7M
      m_demangled.Clear();
116
32.7M
      m_mangled = name;
117
90.6M
    } else {
118
90.6M
      m_demangled = name;
119
90.6M
      m_mangled.Clear();
120
90.6M
    }
121
123M
  } else {
122
0
    m_demangled.Clear();
123
0
    m_mangled.Clear();
124
0
  }
125
123M
}
126
127
// Local helpers for different demangling implementations.
128
0
static char *GetMSVCDemangledStr(std::string_view M) {
129
0
  char *demangled_cstr = llvm::microsoftDemangle(
130
0
      M, nullptr, nullptr,
131
0
      llvm::MSDemangleFlags(
132
0
          llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention |
133
0
          llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType));
134
135
0
  if (Log *log = GetLog(LLDBLog::Demangle)) {
136
0
    if (demangled_cstr && demangled_cstr[0])
137
0
      LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M.data(), demangled_cstr);
138
0
    else
139
0
      LLDB_LOGF(log, "demangled msvc: %s -> error", M.data());
140
0
  }
141
142
0
  return demangled_cstr;
143
0
}
144
145
2.68M
static char *GetItaniumDemangledStr(const char *M) {
146
2.68M
  char *demangled_cstr = nullptr;
147
148
2.68M
  llvm::ItaniumPartialDemangler ipd;
149
2.68M
  bool err = ipd.partialDemangle(M);
150
2.68M
  if (!err) {
151
    // Default buffer and size (will realloc in case it's too small).
152
2.68M
    size_t demangled_size = 80;
153
2.68M
    demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
154
2.68M
    demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
155
156
2.68M
    assert(demangled_cstr &&
157
2.68M
           "finishDemangle must always succeed if partialDemangle did");
158
2.68M
    assert(demangled_cstr[demangled_size - 1] == '\0' &&
159
2.68M
           "Expected demangled_size to return length including trailing null");
160
2.68M
  }
161
162
2.68M
  if (Log *log = GetLog(LLDBLog::Demangle)) {
163
0
    if (demangled_cstr)
164
0
      LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
165
0
    else
166
0
      LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
167
0
  }
168
169
2.68M
  return demangled_cstr;
170
2.68M
}
171
172
4.38k
static char *GetRustV0DemangledStr(std::string_view M) {
173
4.38k
  char *demangled_cstr = llvm::rustDemangle(M);
174
175
4.38k
  if (Log *log = GetLog(LLDBLog::Demangle)) {
176
0
    if (demangled_cstr && demangled_cstr[0])
177
0
      LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr);
178
0
    else
179
0
      LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M);
180
0
  }
181
182
4.38k
  return demangled_cstr;
183
4.38k
}
184
185
58.4k
static char *GetDLangDemangledStr(std::string_view M) {
186
58.4k
  char *demangled_cstr = llvm::dlangDemangle(M);
187
188
58.4k
  if (Log *log = GetLog(LLDBLog::Demangle)) {
189
0
    if (demangled_cstr && demangled_cstr[0])
190
0
      LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr);
191
0
    else
192
0
      LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M);
193
0
  }
194
195
58.4k
  return demangled_cstr;
196
58.4k
}
197
198
// Explicit demangling for scheduled requests during batch processing. This
199
// makes use of ItaniumPartialDemangler's rich demangle info
200
bool Mangled::GetRichManglingInfo(RichManglingContext &context,
201
23.3M
                                  SkipMangledNameFn *skip_mangled_name) {
202
  // Others are not meant to arrive here. ObjC names or C's main() for example
203
  // have their names stored in m_demangled, while m_mangled is empty.
204
23.3M
  assert(m_mangled);
205
206
  // Check whether or not we are interested in this name at all.
207
23.3M
  ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef());
208
23.3M
  if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
209
1.78M
    return false;
210
211
21.5M
  switch (scheme) {
212
0
  case eManglingSchemeNone:
213
    // The current mangled_name_filter would allow llvm_unreachable here.
214
0
    return false;
215
216
21.5M
  case eManglingSchemeItanium:
217
    // We want the rich mangling info here, so we don't care whether or not
218
    // there is a demangled string in the pool already.
219
21.5M
    return context.FromItaniumName(m_mangled);
220
221
0
  case eManglingSchemeMSVC: {
222
    // We have no rich mangling for MSVC-mangled names yet, so first try to
223
    // demangle it if necessary.
224
0
    if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
225
0
      if (char *d = GetMSVCDemangledStr(m_mangled)) {
226
        // Without the rich mangling info we have to demangle the full name.
227
        // Copy it to string pool and connect the counterparts to accelerate
228
        // later access in GetDemangledName().
229
0
        m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
230
0
                                                    m_mangled);
231
0
        ::free(d);
232
0
      } else {
233
0
        m_demangled.SetCString("");
234
0
      }
235
0
    }
236
237
0
    if (m_demangled.IsEmpty()) {
238
      // Cannot demangle it, so don't try parsing.
239
0
      return false;
240
0
    } else {
241
      // Demangled successfully, we can try and parse it with
242
      // CPlusPlusLanguage::MethodName.
243
0
      return context.FromCxxMethodName(m_demangled);
244
0
    }
245
0
  }
246
247
4.08k
  case eManglingSchemeRustV0:
248
24.5k
  case eManglingSchemeD:
249
43.4k
  case eManglingSchemeSwift:
250
    // Rich demangling scheme is not supported
251
43.4k
    return false;
252
21.5M
  }
253
0
  llvm_unreachable("Fully covered switch above!");
254
0
}
255
256
// Generate the demangled name on demand using this accessor. Code in this
257
// class will need to use this accessor if it wishes to decode the demangled
258
// name. The result is cached and will be kept until a new string value is
259
// supplied to this object, or until the end of the object's lifetime.
260
116M
ConstString Mangled::GetDemangledName() const {
261
  // Check to make sure we have a valid mangled name and that we haven't
262
  // already decoded our mangled name.
263
116M
  if (m_mangled && 
m_demangled.IsNull()14.2M
) {
264
    // Don't bother running anything that isn't mangled
265
10.9M
    const char *mangled_name = m_mangled.GetCString();
266
10.9M
    ManglingScheme mangling_scheme =
267
10.9M
        GetManglingScheme(m_mangled.GetStringRef());
268
10.9M
    if (mangling_scheme != eManglingSchemeNone &&
269
10.9M
        
!m_mangled.GetMangledCounterpart(m_demangled)10.9M
) {
270
      // We didn't already mangle this name, demangle it and if all goes well
271
      // add it to our map.
272
2.77M
      char *demangled_name = nullptr;
273
2.77M
      switch (mangling_scheme) {
274
0
      case eManglingSchemeMSVC:
275
0
        demangled_name = GetMSVCDemangledStr(mangled_name);
276
0
        break;
277
2.68M
      case eManglingSchemeItanium: {
278
2.68M
        demangled_name = GetItaniumDemangledStr(mangled_name);
279
2.68M
        break;
280
0
      }
281
4.38k
      case eManglingSchemeRustV0:
282
4.38k
        demangled_name = GetRustV0DemangledStr(m_mangled);
283
4.38k
        break;
284
58.4k
      case eManglingSchemeD:
285
58.4k
        demangled_name = GetDLangDemangledStr(m_mangled);
286
58.4k
        break;
287
27.4k
      case eManglingSchemeSwift:
288
        // Demangling a swift name requires the swift compiler. This is
289
        // explicitly unsupported on llvm.org.
290
27.4k
        break;
291
0
      case eManglingSchemeNone:
292
0
        llvm_unreachable("eManglingSchemeNone was handled already");
293
2.77M
      }
294
2.77M
      if (demangled_name) {
295
2.68M
        m_demangled.SetStringWithMangledCounterpart(
296
2.68M
            llvm::StringRef(demangled_name), m_mangled);
297
2.68M
        free(demangled_name);
298
2.68M
      }
299
2.77M
    }
300
10.9M
    if (m_demangled.IsNull()) {
301
      // Set the demangled string to the empty string to indicate we tried to
302
      // parse it once and failed.
303
96.4k
      m_demangled.SetCString("");
304
96.4k
    }
305
10.9M
  }
306
307
116M
  return m_demangled;
308
116M
}
309
310
66
ConstString Mangled::GetDisplayDemangledName() const {
311
66
  return GetDemangledName();
312
66
}
313
314
180
bool Mangled::NameMatches(const RegularExpression &regex) const {
315
180
  if (m_mangled && 
regex.Execute(m_mangled.GetStringRef())62
)
316
12
    return true;
317
318
168
  ConstString demangled = GetDemangledName();
319
168
  return demangled && regex.Execute(demangled.GetStringRef());
320
180
}
321
322
// Get the demangled name if there is one, else return the mangled name.
323
32.4M
ConstString Mangled::GetName(Mangled::NamePreference preference) const {
324
32.4M
  if (preference == ePreferMangled && 
m_mangled29.5M
)
325
10.0M
    return m_mangled;
326
327
  // Call the accessor to make sure we get a demangled name in case it hasn't
328
  // been demangled yet...
329
22.4M
  ConstString demangled = GetDemangledName();
330
331
22.4M
  if (preference == ePreferDemangledWithoutArguments) {
332
28.8k
    if (Language *lang = Language::FindPlugin(GuessLanguage())) {
333
14.6k
      return lang->GetDemangledFunctionNameWithoutArguments(*this);
334
14.6k
    }
335
28.8k
  }
336
22.4M
  if (preference == ePreferDemangled) {
337
2.84M
    if (demangled)
338
2.73M
      return demangled;
339
112k
    return m_mangled;
340
2.84M
  }
341
19.5M
  return demangled;
342
22.4M
}
343
344
// Dump a Mangled object to stream "s". We don't force our demangled name to be
345
// computed currently (we don't use the accessor).
346
20
void Mangled::Dump(Stream *s) const {
347
20
  if (m_mangled) {
348
4
    *s << ", mangled = " << m_mangled;
349
4
  }
350
20
  if (m_demangled) {
351
19
    const char *demangled = m_demangled.AsCString();
352
19
    s->Printf(", demangled = %s", demangled[0] ? demangled : 
"<error>"0
);
353
19
  }
354
20
}
355
356
// Dumps a debug version of this string with extra object and state information
357
// to stream "s".
358
0
void Mangled::DumpDebug(Stream *s) const {
359
0
  s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
360
0
            static_cast<const void *>(this));
361
0
  m_mangled.DumpDebug(s);
362
0
  s->Printf(", demangled = ");
363
0
  m_demangled.DumpDebug(s);
364
0
}
365
366
// Return the size in byte that this object takes in memory. The size includes
367
// the size of the objects it owns, and not the strings that it references
368
// because they are shared strings.
369
0
size_t Mangled::MemorySize() const {
370
0
  return m_mangled.MemorySize() + m_demangled.MemorySize();
371
0
}
372
373
// We "guess" the language because we can't determine a symbol's language from
374
// it's name.  For example, a Pascal symbol can be mangled using the C++
375
// Itanium scheme, and defined in a compilation unit within the same module as
376
// other C++ units.  In addition, different targets could have different ways
377
// of mangling names from a given language, likewise the compilation units
378
// within those targets.
379
172k
lldb::LanguageType Mangled::GuessLanguage() const {
380
172k
  lldb::LanguageType result = lldb::eLanguageTypeUnknown;
381
  // Ask each language plugin to check if the mangled name belongs to it.
382
1.11M
  Language::ForEach([this, &result](Language *l) {
383
1.11M
    if (l->SymbolNameFitsToLanguage(*this)) {
384
42.1k
      result = l->GetLanguageType();
385
42.1k
      return false;
386
42.1k
    }
387
1.07M
    return true;
388
1.11M
  });
389
172k
  return result;
390
172k
}
391
392
// Dump OBJ to the supplied stream S.
393
0
Stream &operator<<(Stream &s, const Mangled &obj) {
394
0
  if (obj.GetMangledName())
395
0
    s << "mangled = '" << obj.GetMangledName() << "'";
396
397
0
  ConstString demangled = obj.GetDemangledName();
398
0
  if (demangled)
399
0
    s << ", demangled = '" << demangled << '\'';
400
0
  else
401
0
    s << ", demangled = <error>";
402
0
  return s;
403
0
}
404
405
// When encoding Mangled objects we can get away with encoding as little
406
// information as is required. The enumeration below helps us to efficiently
407
// encode Mangled objects.
408
enum MangledEncoding {
409
  /// If the Mangled object has neither a mangled name or demangled name we can
410
  /// encode the object with one zero byte using the Empty enumeration.
411
  Empty = 0u,
412
  /// If the Mangled object has only a demangled name and no mangled named, we
413
  /// can encode only the demangled name.
414
  DemangledOnly = 1u,
415
  /// If the mangle name can calculate the demangled name (it is the
416
  /// mangled/demangled counterpart), then we only need to encode the mangled
417
  /// name as the demangled name can be recomputed.
418
  MangledOnly = 2u,
419
  /// If we have a Mangled object with two different names that are not related
420
  /// then we need to save both strings. This can happen if we have a name that
421
  /// isn't a true mangled name, but we want to be able to lookup a symbol by
422
  /// name and type in the symbol table. We do this for Objective C symbols like
423
  /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to
424
  /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to
425
  /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it
426
  /// would fail, but in these cases we want these unrelated names to be
427
  /// preserved.
428
  MangledAndDemangled = 3u
429
};
430
431
bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
432
45
                     const StringTableReader &strtab) {
433
45
  m_mangled.Clear();
434
45
  m_demangled.Clear();
435
45
  MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr);
436
45
  switch (encoding) {
437
2
    case Empty:
438
2
      return true;
439
440
38
    case DemangledOnly:
441
38
      m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
442
38
      return true;
443
444
3
    case MangledOnly:
445
3
      m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
446
3
      return true;
447
448
2
    case MangledAndDemangled:
449
2
      m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
450
2
      m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr)));
451
2
      return true;
452
45
  }
453
0
  return false;
454
45
}
455
/// The encoding format for the Mangled object is as follows:
456
///
457
/// uint8_t encoding;
458
/// char str1[]; (only if DemangledOnly, MangledOnly)
459
/// char str2[]; (only if MangledAndDemangled)
460
///
461
/// The strings are stored as NULL terminated UTF8 strings and str1 and str2
462
/// are only saved if we need them based on the encoding.
463
///
464
/// Some mangled names have a mangled name that can be demangled by the built
465
/// in demanglers. These kinds of mangled objects know when the mangled and
466
/// demangled names are the counterparts for each other. This is done because
467
/// demangling is very expensive and avoiding demangling the same name twice
468
/// saves us a lot of compute time. For these kinds of names we only need to
469
/// save the mangled name and have the encoding set to "MangledOnly".
470
///
471
/// If a mangled obejct has only a demangled name, then we save only that string
472
/// and have the encoding set to "DemangledOnly".
473
///
474
/// Some mangled objects have both mangled and demangled names, but the
475
/// demangled name can not be computed from the mangled name. This is often used
476
/// for runtime named, like Objective C runtime V2 and V3 names. Both these
477
/// names must be saved and the encoding is set to "MangledAndDemangled".
478
///
479
/// For a Mangled object with no names, we only need to set the encoding to
480
/// "Empty" and not store any string values.
481
77
void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const {
482
77
  MangledEncoding encoding = Empty;
483
77
  if (m_mangled) {
484
4
    encoding = MangledOnly;
485
4
    if (m_demangled) {
486
      // We have both mangled and demangled names. If the demangled name is the
487
      // counterpart of the mangled name, then we only need to save the mangled
488
      // named. If they are different, we need to save both.
489
3
      ConstString s;
490
3
      if (!(m_mangled.GetMangledCounterpart(s) && 
s == m_demangled1
))
491
2
        encoding = MangledAndDemangled;
492
3
    }
493
73
  } else if (m_demangled) {
494
71
    encoding = DemangledOnly;
495
71
  }
496
77
  file.AppendU8(encoding);
497
77
  switch (encoding) {
498
2
    case Empty:
499
2
      break;
500
71
    case DemangledOnly:
501
71
      file.AppendU32(strtab.Add(m_demangled));
502
71
      break;
503
2
    case MangledOnly:
504
2
      file.AppendU32(strtab.Add(m_mangled));
505
2
      break;
506
2
    case MangledAndDemangled:
507
2
      file.AppendU32(strtab.Add(m_mangled));
508
2
      file.AppendU32(strtab.Add(m_demangled));
509
2
      break;
510
77
  }
511
77
}