1d650cbc3SHaowei Wu //===- llvm/unittests/TextAPI/YAMLTest.cpp --------------------------------===// 2d650cbc3SHaowei Wu // 3d650cbc3SHaowei Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4d650cbc3SHaowei Wu // See https://llvm.org/LICENSE.txt for license information. 5d650cbc3SHaowei Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d650cbc3SHaowei Wu // 7d650cbc3SHaowei Wu //===-----------------------------------------------------------------------===/ 8d650cbc3SHaowei Wu 9d650cbc3SHaowei Wu #include "llvm/ADT/StringRef.h" 1061fa9afeSHaowei Wu #include "llvm/BinaryFormat/ELF.h" 1161fa9afeSHaowei Wu #include "llvm/InterfaceStub/IFSHandler.h" 1261fa9afeSHaowei Wu #include "llvm/InterfaceStub/IFSStub.h" 13d650cbc3SHaowei Wu #include "llvm/Support/Error.h" 14d650cbc3SHaowei Wu #include "llvm/Testing/Support/Error.h" 15d650cbc3SHaowei Wu #include "gtest/gtest.h" 16d650cbc3SHaowei Wu #include <string> 17d650cbc3SHaowei Wu 18d650cbc3SHaowei Wu using namespace llvm; 19d650cbc3SHaowei Wu using namespace llvm::ELF; 206103fdfaSHaowei Wu using namespace llvm::ifs; 21d650cbc3SHaowei Wu 22d650cbc3SHaowei Wu void compareByLine(StringRef LHS, StringRef RHS) { 23d650cbc3SHaowei Wu StringRef Line1; 24d650cbc3SHaowei Wu StringRef Line2; 25d650cbc3SHaowei Wu while (LHS.size() > 0 && RHS.size() > 0) { 26d650cbc3SHaowei Wu std::tie(Line1, LHS) = LHS.split('\n'); 27d650cbc3SHaowei Wu std::tie(Line2, RHS) = RHS.split('\n'); 28d650cbc3SHaowei Wu // Comparing StringRef objects works, but has messy output when not equal. 29d650cbc3SHaowei Wu // Using STREQ on StringRef.data() doesn't work since these substrings are 30d650cbc3SHaowei Wu // not null terminated. 31d650cbc3SHaowei Wu // This is inefficient, but forces null terminated strings that can be 32d650cbc3SHaowei Wu // cleanly compared. 33d650cbc3SHaowei Wu EXPECT_STREQ(Line1.str().data(), Line2.str().data()); 34d650cbc3SHaowei Wu } 35d650cbc3SHaowei Wu } 36d650cbc3SHaowei Wu 37d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLReadableTBE) { 388b4acb06SHaowei Wu const char Data[] = "--- !ifs-v1\n" 3961fa9afeSHaowei Wu "IfsVersion: 1.0\n" 408b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: " 418b4acb06SHaowei Wu "little, BitWidth: 64 }\n" 42d650cbc3SHaowei Wu "NeededLibs: [libc.so, libfoo.so, libbar.so]\n" 43d650cbc3SHaowei Wu "Symbols:\n" 448b4acb06SHaowei Wu " - { Name: foo, Type: Func, Undefined: true }\n" 45d650cbc3SHaowei Wu "...\n"; 4661fa9afeSHaowei Wu Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 47d650cbc3SHaowei Wu ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); 4861fa9afeSHaowei Wu std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get()); 49d650cbc3SHaowei Wu EXPECT_NE(Stub.get(), nullptr); 503361a364SKazu Hirata EXPECT_FALSE(Stub->SoName.has_value()); 513361a364SKazu Hirata EXPECT_TRUE(Stub->Target.Arch.has_value()); 5267ba5c50SFangrui Song EXPECT_EQ(*Stub->Target.Arch, (uint16_t)llvm::ELF::EM_X86_64); 53d650cbc3SHaowei Wu EXPECT_EQ(Stub->NeededLibs.size(), 3u); 54d650cbc3SHaowei Wu EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so"); 55d650cbc3SHaowei Wu EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so"); 56d650cbc3SHaowei Wu EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so"); 57d650cbc3SHaowei Wu } 58d650cbc3SHaowei Wu 59*8e9c5319SHaowei TEST(ElfYamlTextAPI, YAMLReadsInvalidSymbols) { 60*8e9c5319SHaowei const char Data[] = 61*8e9c5319SHaowei "--- !ifs-v1\n" 62*8e9c5319SHaowei "IfsVersion: 1.0\n" 63*8e9c5319SHaowei "SoName: test.so\n" 64*8e9c5319SHaowei "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, " 65*8e9c5319SHaowei "BitWidth: 64 }\n" 66*8e9c5319SHaowei "Symbols:\n" 67*8e9c5319SHaowei " - { Name: not, Type: File, Undefined: true, Size: 111, " 68*8e9c5319SHaowei "Weak: true, Warning: \'All fields populated!\' }\n" 69*8e9c5319SHaowei "...\n"; 70*8e9c5319SHaowei Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 71*8e9c5319SHaowei ASSERT_THAT_ERROR( 72*8e9c5319SHaowei StubOrErr.takeError(), 73*8e9c5319SHaowei FailedWithMessage("IFS symbol type for symbol 'not' is unsupported")); 74*8e9c5319SHaowei } 75*8e9c5319SHaowei 76d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) { 778b4acb06SHaowei Wu const char Data[] = 788b4acb06SHaowei Wu "--- !ifs-v1\n" 7961fa9afeSHaowei Wu "IfsVersion: 1.0\n" 80d650cbc3SHaowei Wu "SoName: test.so\n" 818b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, " 828b4acb06SHaowei Wu "BitWidth: 64 }\n" 83d650cbc3SHaowei Wu "Symbols:\n" 848b4acb06SHaowei Wu " - { Name: bar, Type: Object, Size: 42 }\n" 858b4acb06SHaowei Wu " - { Name: baz, Type: TLS, Size: 3 }\n" 868b4acb06SHaowei Wu " - { Name: foo, Type: Func, Warning: \"Deprecated!\" }\n" 878b4acb06SHaowei Wu " - { Name: nor, Type: NoType, Undefined: true }\n" 88*8e9c5319SHaowei " - { Name: not, Type: NoType, Undefined: true, Size: 111, " 89d650cbc3SHaowei Wu "Weak: true, Warning: \'All fields populated!\' }\n" 90d650cbc3SHaowei Wu "...\n"; 9161fa9afeSHaowei Wu Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 92d650cbc3SHaowei Wu ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); 9361fa9afeSHaowei Wu std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get()); 94d650cbc3SHaowei Wu EXPECT_NE(Stub.get(), nullptr); 95d152e50cSKazu Hirata EXPECT_TRUE(Stub->SoName); 96d650cbc3SHaowei Wu EXPECT_STREQ(Stub->SoName->c_str(), "test.so"); 97d650cbc3SHaowei Wu EXPECT_EQ(Stub->Symbols.size(), 5u); 98d650cbc3SHaowei Wu 99d650cbc3SHaowei Wu auto Iterator = Stub->Symbols.begin(); 10061fa9afeSHaowei Wu IFSSymbol const &SymBar = *Iterator++; 101d650cbc3SHaowei Wu EXPECT_STREQ(SymBar.Name.c_str(), "bar"); 102a74d9e74SAlex Brachet EXPECT_EQ(*SymBar.Size, 42u); 10361fa9afeSHaowei Wu EXPECT_EQ(SymBar.Type, IFSSymbolType::Object); 104d650cbc3SHaowei Wu EXPECT_FALSE(SymBar.Undefined); 105d650cbc3SHaowei Wu EXPECT_FALSE(SymBar.Weak); 106d152e50cSKazu Hirata EXPECT_FALSE(SymBar.Warning); 107d650cbc3SHaowei Wu 10861fa9afeSHaowei Wu IFSSymbol const &SymBaz = *Iterator++; 109d650cbc3SHaowei Wu EXPECT_STREQ(SymBaz.Name.c_str(), "baz"); 110a74d9e74SAlex Brachet EXPECT_EQ(*SymBaz.Size, 3u); 11161fa9afeSHaowei Wu EXPECT_EQ(SymBaz.Type, IFSSymbolType::TLS); 112d650cbc3SHaowei Wu EXPECT_FALSE(SymBaz.Undefined); 113d650cbc3SHaowei Wu EXPECT_FALSE(SymBaz.Weak); 1143361a364SKazu Hirata EXPECT_FALSE(SymBaz.Warning.has_value()); 115d650cbc3SHaowei Wu 11661fa9afeSHaowei Wu IFSSymbol const &SymFoo = *Iterator++; 117d650cbc3SHaowei Wu EXPECT_STREQ(SymFoo.Name.c_str(), "foo"); 1183361a364SKazu Hirata EXPECT_FALSE(SymFoo.Size.has_value()); 11961fa9afeSHaowei Wu EXPECT_EQ(SymFoo.Type, IFSSymbolType::Func); 120d650cbc3SHaowei Wu EXPECT_FALSE(SymFoo.Undefined); 121d650cbc3SHaowei Wu EXPECT_FALSE(SymFoo.Weak); 1223361a364SKazu Hirata EXPECT_TRUE(SymFoo.Warning.has_value()); 123d650cbc3SHaowei Wu EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!"); 124d650cbc3SHaowei Wu 12561fa9afeSHaowei Wu IFSSymbol const &SymNor = *Iterator++; 126d650cbc3SHaowei Wu EXPECT_STREQ(SymNor.Name.c_str(), "nor"); 1273361a364SKazu Hirata EXPECT_FALSE(SymNor.Size.has_value()); 12861fa9afeSHaowei Wu EXPECT_EQ(SymNor.Type, IFSSymbolType::NoType); 129d650cbc3SHaowei Wu EXPECT_TRUE(SymNor.Undefined); 130d650cbc3SHaowei Wu EXPECT_FALSE(SymNor.Weak); 1313361a364SKazu Hirata EXPECT_FALSE(SymNor.Warning.has_value()); 132d650cbc3SHaowei Wu 13361fa9afeSHaowei Wu IFSSymbol const &SymNot = *Iterator++; 134d650cbc3SHaowei Wu EXPECT_STREQ(SymNot.Name.c_str(), "not"); 135a74d9e74SAlex Brachet EXPECT_EQ(*SymNot.Size, 111u); 136*8e9c5319SHaowei EXPECT_EQ(SymNot.Type, IFSSymbolType::NoType); 137d650cbc3SHaowei Wu EXPECT_TRUE(SymNot.Undefined); 138d650cbc3SHaowei Wu EXPECT_TRUE(SymNot.Weak); 139d152e50cSKazu Hirata EXPECT_TRUE(SymNot.Warning); 140d650cbc3SHaowei Wu EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!"); 141d650cbc3SHaowei Wu } 142d650cbc3SHaowei Wu 143d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) { 1448b4acb06SHaowei Wu const char Data[] = "--- !ifs-v1\n" 14561fa9afeSHaowei Wu "IfsVersion: 1.0\n" 146d650cbc3SHaowei Wu "SoName: test.so\n" 1478b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: " 1488b4acb06SHaowei Wu "little, BitWidth: 64 }\n" 1498b4acb06SHaowei Wu "Symbols: []\n" 150d650cbc3SHaowei Wu "...\n"; 15161fa9afeSHaowei Wu Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 152d650cbc3SHaowei Wu ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); 15361fa9afeSHaowei Wu std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get()); 154d650cbc3SHaowei Wu EXPECT_NE(Stub.get(), nullptr); 155d650cbc3SHaowei Wu EXPECT_EQ(0u, Stub->Symbols.size()); 156d650cbc3SHaowei Wu } 157d650cbc3SHaowei Wu 158d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLUnreadableTBE) { 159d650cbc3SHaowei Wu // Can't read: wrong format/version. 160d650cbc3SHaowei Wu const char Data[] = "--- !tapi-tbz\n" 16161fa9afeSHaowei Wu "IfsVersion: z.3\n" 162d650cbc3SHaowei Wu "SoName: test.so\n" 1638b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: " 1648b4acb06SHaowei Wu "little, BitWidth: 64 }\n" 165d650cbc3SHaowei Wu "Symbols:\n" 166d650cbc3SHaowei Wu " foo: { Type: Func, Undefined: true }\n"; 16761fa9afeSHaowei Wu Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 168d650cbc3SHaowei Wu ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed()); 169d650cbc3SHaowei Wu } 170d650cbc3SHaowei Wu 171acb33cbaSCyndy Ishida TEST(ElfYamlTextAPI, YAMLUnsupportedVersion) { 1728b4acb06SHaowei Wu const char Data[] = "--- !ifs-v1\n" 17361fa9afeSHaowei Wu "IfsVersion: 9.9.9\n" 174acb33cbaSCyndy Ishida "SoName: test.so\n" 1758b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: " 1768b4acb06SHaowei Wu "little, BitWidth: 64 }\n" 1778b4acb06SHaowei Wu "Symbols: []\n" 178acb33cbaSCyndy Ishida "...\n"; 17961fa9afeSHaowei Wu Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data); 180acb33cbaSCyndy Ishida std::string ErrorMessage = toString(StubOrErr.takeError()); 18161fa9afeSHaowei Wu EXPECT_EQ("IFS version 9.9.9 is unsupported.", ErrorMessage); 182acb33cbaSCyndy Ishida } 183acb33cbaSCyndy Ishida 184d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) { 185d650cbc3SHaowei Wu const char Expected[] = 1868b4acb06SHaowei Wu "--- !ifs-v1\n" 18761fa9afeSHaowei Wu "IfsVersion: 1.0\n" 1888b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: " 1898b4acb06SHaowei Wu "little, BitWidth: 64 }\n" 190d650cbc3SHaowei Wu "Symbols:\n" 1918b4acb06SHaowei Wu " - { Name: bar, Type: Func, Weak: true }\n" 1928b4acb06SHaowei Wu " - { Name: foo, Type: NoType, Size: 99, Warning: Does nothing }\n" 1938b4acb06SHaowei Wu " - { Name: nor, Type: Func, Undefined: true }\n" 1948b4acb06SHaowei Wu " - { Name: not, Type: Unknown, Size: 12345678901234 }\n" 195d650cbc3SHaowei Wu "...\n"; 19661fa9afeSHaowei Wu IFSStub Stub; 19761fa9afeSHaowei Wu Stub.IfsVersion = VersionTuple(1, 0); 1988b4acb06SHaowei Wu Stub.Target.Arch = ELF::EM_AARCH64; 19961fa9afeSHaowei Wu Stub.Target.BitWidth = IFSBitWidthType::IFS64; 20061fa9afeSHaowei Wu Stub.Target.Endianness = IFSEndiannessType::Little; 2018b4acb06SHaowei Wu Stub.Target.ObjectFormat = "ELF"; 2028b4acb06SHaowei Wu 20361fa9afeSHaowei Wu IFSSymbol SymBar("bar"); 2048b4acb06SHaowei Wu SymBar.Size = 128u; 20561fa9afeSHaowei Wu SymBar.Type = IFSSymbolType::Func; 2068b4acb06SHaowei Wu SymBar.Undefined = false; 2078b4acb06SHaowei Wu SymBar.Weak = true; 208d650cbc3SHaowei Wu 20961fa9afeSHaowei Wu IFSSymbol SymFoo("foo"); 210d650cbc3SHaowei Wu SymFoo.Size = 99u; 21161fa9afeSHaowei Wu SymFoo.Type = IFSSymbolType::NoType; 212d650cbc3SHaowei Wu SymFoo.Undefined = false; 213d650cbc3SHaowei Wu SymFoo.Weak = false; 214d650cbc3SHaowei Wu SymFoo.Warning = "Does nothing"; 215d650cbc3SHaowei Wu 21661fa9afeSHaowei Wu IFSSymbol SymNor("nor"); 217d650cbc3SHaowei Wu SymNor.Size = 1234u; 21861fa9afeSHaowei Wu SymNor.Type = IFSSymbolType::Func; 219d650cbc3SHaowei Wu SymNor.Undefined = true; 220d650cbc3SHaowei Wu SymNor.Weak = false; 221d650cbc3SHaowei Wu 22261fa9afeSHaowei Wu IFSSymbol SymNot("not"); 223d650cbc3SHaowei Wu SymNot.Size = 12345678901234u; 22461fa9afeSHaowei Wu SymNot.Type = IFSSymbolType::Unknown; 225d650cbc3SHaowei Wu SymNot.Undefined = false; 226d650cbc3SHaowei Wu SymNot.Weak = false; 227d650cbc3SHaowei Wu 2288b4acb06SHaowei Wu // Symbol order is preserved instead of being sorted. 2298b4acb06SHaowei Wu Stub.Symbols.push_back(SymBar); 2308b4acb06SHaowei Wu Stub.Symbols.push_back(SymFoo); 2318b4acb06SHaowei Wu Stub.Symbols.push_back(SymNor); 2328b4acb06SHaowei Wu Stub.Symbols.push_back(SymNot); 233d650cbc3SHaowei Wu 234d650cbc3SHaowei Wu // Ensure move constructor works as expected. 23561fa9afeSHaowei Wu IFSStub Moved = std::move(Stub); 236d650cbc3SHaowei Wu 237d650cbc3SHaowei Wu std::string Result; 238d650cbc3SHaowei Wu raw_string_ostream OS(Result); 23961fa9afeSHaowei Wu ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Moved), Succeeded()); 240d650cbc3SHaowei Wu compareByLine(Result.c_str(), Expected); 241d650cbc3SHaowei Wu } 242d650cbc3SHaowei Wu 243d650cbc3SHaowei Wu TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) { 2448b4acb06SHaowei Wu const char Expected[] = "--- !ifs-v1\n" 24561fa9afeSHaowei Wu "IfsVersion: 1.0\n" 246d650cbc3SHaowei Wu "SoName: nosyms.so\n" 2478b4acb06SHaowei Wu "Target: { ObjectFormat: ELF, Arch: x86_64, " 2488b4acb06SHaowei Wu "Endianness: little, BitWidth: 64 }\n" 249d650cbc3SHaowei Wu "NeededLibs:\n" 250d650cbc3SHaowei Wu " - libc.so\n" 251d650cbc3SHaowei Wu " - libfoo.so\n" 252d650cbc3SHaowei Wu " - libbar.so\n" 2538b4acb06SHaowei Wu "Symbols: []\n" 254d650cbc3SHaowei Wu "...\n"; 25561fa9afeSHaowei Wu IFSStub Stub; 25661fa9afeSHaowei Wu Stub.IfsVersion = VersionTuple(1, 0); 257d650cbc3SHaowei Wu Stub.SoName = "nosyms.so"; 2588b4acb06SHaowei Wu Stub.Target.Arch = ELF::EM_X86_64; 25961fa9afeSHaowei Wu Stub.Target.BitWidth = IFSBitWidthType::IFS64; 26061fa9afeSHaowei Wu Stub.Target.Endianness = IFSEndiannessType::Little; 2618b4acb06SHaowei Wu Stub.Target.ObjectFormat = "ELF"; 262d650cbc3SHaowei Wu Stub.NeededLibs.push_back("libc.so"); 263d650cbc3SHaowei Wu Stub.NeededLibs.push_back("libfoo.so"); 264d650cbc3SHaowei Wu Stub.NeededLibs.push_back("libbar.so"); 265d650cbc3SHaowei Wu 266d650cbc3SHaowei Wu std::string Result; 267d650cbc3SHaowei Wu raw_string_ostream OS(Result); 26861fa9afeSHaowei Wu ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Stub), Succeeded()); 269d650cbc3SHaowei Wu compareByLine(Result.c_str(), Expected); 270d650cbc3SHaowei Wu } 271