llvm-project/lldb/unittests/Core/MangledTest.cpp
Alex Langford edc64d49de [lldb] Add support for recognizing swift mangled names
Apple maintains a downstream fork of lldb in order to support swift
debugging. Much of that support is isolated to its own plugins, but some
of it is exposed in more generic code. I would like to take some of
the swift support we have downstream and move it upstream to llvm.org in
an effort to 1) reduce downstream maintenance burden, and 2) work
towards solidifying the process of adding new language support to lldb.

Differential Revision: https://reviews.llvm.org/D158470
2023-08-22 10:28:55 -07:00

322 lines
11 KiB
C++

//===-- MangledTest.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace lldb;
using namespace lldb_private;
TEST(MangledTest, ResultForValidName) {
ConstString MangledName("_ZN1a1b1cIiiiEEvm");
Mangled TheMangled(MangledName);
ConstString TheDemangled = TheMangled.GetDemangledName();
ConstString ExpectedResult("void a::b::c<int, int, int>(unsigned long)");
EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
}
TEST(MangledTest, ResultForBlockInvocation) {
ConstString MangledName("___Z1fU13block_pointerFviE_block_invoke");
Mangled TheMangled(MangledName);
ConstString TheDemangled = TheMangled.GetDemangledName();
ConstString ExpectedResult(
"invocation function for block in f(void (int) block_pointer)");
EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
}
TEST(MangledTest, EmptyForInvalidName) {
ConstString MangledName("_ZN1a1b1cmxktpEEvm");
Mangled TheMangled(MangledName);
ConstString TheDemangled = TheMangled.GetDemangledName();
EXPECT_STREQ("", TheDemangled.GetCString());
}
TEST(MangledTest, ResultForValidRustV0Name) {
ConstString mangled_name("_RNvC1a4main");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();
ConstString expected_result("a::main");
EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
}
TEST(MangledTest, EmptyForInvalidRustV0Name) {
ConstString mangled_name("_RRR");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();
EXPECT_STREQ("", the_demangled.GetCString());
}
TEST(MangledTest, ResultForValidDLangName) {
ConstString mangled_name("_Dmain");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();
ConstString expected_result("D main");
EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
}
TEST(MangledTest, EmptyForInvalidDLangName) {
ConstString mangled_name("_DDD");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();
EXPECT_STREQ("", the_demangled.GetCString());
}
TEST(MangledTest, RecognizeSwiftMangledNames) {
llvm::StringRef valid_swift_mangled_names[] = {
"_TtC4main7MyClass", // Mangled objc class name
"_TtP4main3Foo_", // Mangld objc protocol name
"$s4main3BarCACycfC", // Mangled name
"_$s4main3BarCACycfC", // Mangled name with leading underscore
"$S4main3BarCACycfC", // Older swift mangled name
"_$S4main3BarCACycfC", // Older swift mangled name
// with leading underscore
// Mangled swift filename
"@__swiftmacro_4main16FunVariableNames9OptionSetfMm_.swift",
};
for (llvm::StringRef mangled : valid_swift_mangled_names)
EXPECT_EQ(Mangled::GetManglingScheme(mangled),
Mangled::eManglingSchemeSwift);
}
TEST(MangledTest, BoolConversionOperator) {
{
ConstString MangledName("_ZN1a1b1cIiiiEEvm");
Mangled TheMangled(MangledName);
EXPECT_EQ(true, bool(TheMangled));
EXPECT_EQ(false, !TheMangled);
}
{
ConstString UnmangledName("puts");
Mangled TheMangled(UnmangledName);
EXPECT_EQ(true, bool(TheMangled));
EXPECT_EQ(false, !TheMangled);
}
{
Mangled TheMangled{};
EXPECT_EQ(false, bool(TheMangled));
EXPECT_EQ(true, !TheMangled);
}
}
TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
subsystems;
auto ExpectedFile = TestFile::fromYaml(R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000010
Size: 0x20
- Name: .anothertext
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x0000000000000010
AddressAlign: 0x0000000000000010
Size: 0x40
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
Address: 0x00000000000000A8
AddressAlign: 0x0000000000000004
Content: '01000000'
Symbols:
- Name: somedata
Type: STT_OBJECT
Section: .anothertext
Value: 0x0000000000000045
Binding: STB_GLOBAL
- Name: main
Type: STT_FUNC
Section: .anothertext
Value: 0x0000000000000010
Size: 0x000000000000003F
Binding: STB_GLOBAL
- Name: _Z3foov
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: puts@GLIBC_2.5
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: puts@GLIBC_2.6
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _Z5annotv@VERSION3
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZN1AC2Ev
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZN1AD2Ev
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZN1A3barEv
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZGVZN4llvm4dbgsEvE7thestrm
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZZN4llvm4dbgsEvE7thestrm
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _ZTVN5clang4DeclE
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: -[ObjCfoo]
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: +[B ObjCbar(WithCategory)]
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
- Name: _Z12undemangableEvx42
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
Binding: STB_GLOBAL
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
auto M = std::make_shared<Module>(ExpectedFile->moduleSpec());
auto Count = [M](const char *Name, FunctionNameType Type) -> int {
SymbolContextList SymList;
M->FindFunctionSymbols(ConstString(Name), Type, SymList);
return SymList.GetSize();
};
// Unmangled
EXPECT_EQ(1, Count("main", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("main", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("main", eFunctionNameTypeMethod));
// Itanium mangled
EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("foo", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("foo", eFunctionNameTypeMethod));
// Unmangled with linker annotation
EXPECT_EQ(1, Count("puts@GLIBC_2.5", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("puts@GLIBC_2.6", eFunctionNameTypeFull));
EXPECT_EQ(2, Count("puts", eFunctionNameTypeFull));
EXPECT_EQ(2, Count("puts", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("puts", eFunctionNameTypeMethod));
// Itanium mangled with linker annotation
EXPECT_EQ(1, Count("_Z5annotv@VERSION3", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("annot", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("annot", eFunctionNameTypeMethod));
// Itanium mangled ctor A::A()
EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("A", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("A", eFunctionNameTypeBase));
// Itanium mangled dtor A::~A()
EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("~A", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("~A", eFunctionNameTypeBase));
// Itanium mangled method A::bar()
EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("bar", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("bar", eFunctionNameTypeBase));
// Itanium mangled names that are explicitly excluded from parsing
EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("Decl", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("Decl", eFunctionNameTypeBase));
// ObjC mangled static
EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("ObjCfoo", eFunctionNameTypeMethod));
// ObjC mangled method with category
EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("ObjCbar", eFunctionNameTypeMethod));
// Invalid things: unable to decode but still possible to find by full name
EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeFull));
EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("_Z12undemangableEvx42", eFunctionNameTypeMethod));
EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
}