|  | //===-- MangledTest.cpp -----------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" | 
|  | #include "Plugins/SymbolVendor/ELF/SymbolVendorELF.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 "gtest/gtest.h" | 
|  |  | 
|  | using namespace lldb; | 
|  | using namespace lldb_private; | 
|  |  | 
|  | TEST(MangledTest, ResultForValidName) { | 
|  | ConstString MangledName("_ZN1a1b1cIiiiEEvm"); | 
|  | bool IsMangled = true; | 
|  |  | 
|  | Mangled TheMangled(MangledName, IsMangled); | 
|  | const ConstString &TheDemangled = | 
|  | TheMangled.GetDemangledName(eLanguageTypeC_plus_plus); | 
|  |  | 
|  | ConstString ExpectedResult("void a::b::c<int, int, int>(unsigned long)"); | 
|  | EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString()); | 
|  | } | 
|  |  | 
|  | TEST(MangledTest, EmptyForInvalidName) { | 
|  | ConstString MangledName("_ZN1a1b1cmxktpEEvm"); | 
|  | bool IsMangled = true; | 
|  |  | 
|  | Mangled TheMangled(MangledName, IsMangled); | 
|  | const ConstString &TheDemangled = | 
|  | TheMangled.GetDemangledName(eLanguageTypeC_plus_plus); | 
|  |  | 
|  | EXPECT_STREQ("", TheDemangled.GetCString()); | 
|  | } | 
|  |  | 
|  | #define ASSERT_NO_ERROR(x)                                                     \ | 
|  | if (std::error_code ASSERT_NO_ERROR_ec = x) {                                \ | 
|  | llvm::SmallString<128> MessageStorage;                                     \ | 
|  | llvm::raw_svector_ostream Message(MessageStorage);                         \ | 
|  | Message << #x ": did not return errc::success.\n"                          \ | 
|  | << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"          \ | 
|  | << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";      \ | 
|  | GTEST_FATAL_FAILURE_(MessageStorage.c_str());                              \ | 
|  | } else {                                                                     \ | 
|  | } | 
|  |  | 
|  | TEST(MangledTest, NameIndexes_FindFunctionSymbols) { | 
|  | FileSystem::Initialize(); | 
|  | HostInfo::Initialize(); | 
|  | ObjectFileELF::Initialize(); | 
|  | SymbolVendorELF::Initialize(); | 
|  |  | 
|  | std::string Yaml = GetInputFilePath("mangled-function-names.yaml"); | 
|  | llvm::SmallString<128> Obj; | 
|  | ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile( | 
|  | "mangled-function-names-%%%%%%", "obj", Obj)); | 
|  |  | 
|  | llvm::FileRemover Deleter(Obj); | 
|  | llvm::StringRef Args[] = {YAML2OBJ, Yaml}; | 
|  | llvm::StringRef ObjRef = Obj; | 
|  | const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, ObjRef, | 
|  | llvm::None}; | 
|  | ASSERT_EQ(0, | 
|  | llvm::sys::ExecuteAndWait(YAML2OBJ, Args, llvm::None, redirects)); | 
|  | uint64_t Size; | 
|  | ASSERT_NO_ERROR(llvm::sys::fs::file_size(Obj, Size)); | 
|  | ASSERT_GT(Size, 0u); | 
|  |  | 
|  | ModuleSpec Spec{FileSpec(Obj)}; | 
|  | Spec.GetSymbolFileSpec().SetFile(Obj, FileSpec::Style::native); | 
|  | auto M = std::make_shared<Module>(Spec); | 
|  |  | 
|  | auto Count = [M](const char *Name, FunctionNameType Type) -> int { | 
|  | SymbolContextList SymList; | 
|  | return M->FindFunctionSymbols(ConstString(Name), Type, SymList); | 
|  | }; | 
|  |  | 
|  | // 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)); | 
|  |  | 
|  | SymbolVendorELF::Terminate(); | 
|  | ObjectFileELF::Terminate(); | 
|  | HostInfo::Terminate(); | 
|  | FileSystem::Terminate(); | 
|  | } |