xref: /llvm-project/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp (revision 52b48a70d3752f9db36ddcfd26d0451c009b19fc)
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