[yaml2obj/obj2yaml] - Do not trigger llvm_unreachable when dumping/parsing relocation...
[llvm-complete.git] / unittests / TextAPI / ELFYAMLTest.cpp
blob8217507b5a5dc5e20d9831f1bc4981353c6bc883
1 //===- llvm/unittests/TextAPI/YAMLTest.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 //===-----------------------------------------------------------------------===/
9 #include "llvm/ADT/StringRef.h"
10 #include "llvm/TextAPI/ELF/ELFStub.h"
11 #include "llvm/TextAPI/ELF/TBEHandler.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Testing/Support/Error.h"
14 #include "gtest/gtest.h"
15 #include <string>
17 using namespace llvm;
18 using namespace llvm::ELF;
19 using namespace llvm::elfabi;
21 void compareByLine(StringRef LHS, StringRef RHS) {
22 StringRef Line1;
23 StringRef Line2;
24 while (LHS.size() > 0 && RHS.size() > 0) {
25 std::tie(Line1, LHS) = LHS.split('\n');
26 std::tie(Line2, RHS) = RHS.split('\n');
27 // Comparing StringRef objects works, but has messy output when not equal.
28 // Using STREQ on StringRef.data() doesn't work since these substrings are
29 // not null terminated.
30 // This is inefficient, but forces null terminated strings that can be
31 // cleanly compared.
32 EXPECT_STREQ(Line1.str().data(), Line2.str().data());
36 TEST(ElfYamlTextAPI, YAMLReadableTBE) {
37 const char Data[] = "--- !tapi-tbe\n"
38 "TbeVersion: 1.0\n"
39 "Arch: x86_64\n"
40 "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
41 "Symbols:\n"
42 " foo: { Type: Func, Undefined: true }\n"
43 "...\n";
44 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
45 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
46 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
47 EXPECT_NE(Stub.get(), nullptr);
48 EXPECT_FALSE(Stub->SoName.hasValue());
49 EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
50 EXPECT_EQ(Stub->NeededLibs.size(), 3u);
51 EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
52 EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
53 EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");
56 TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
57 const char Data[] = "--- !tapi-tbe\n"
58 "TbeVersion: 1.0\n"
59 "SoName: test.so\n"
60 "Arch: x86_64\n"
61 "Symbols:\n"
62 " bar: { Type: Object, Size: 42 }\n"
63 " baz: { Type: TLS, Size: 3 }\n"
64 " foo: { Type: Func, Warning: \"Deprecated!\" }\n"
65 " nor: { Type: NoType, Undefined: true }\n"
66 " not: { Type: File, Undefined: true, Size: 111, "
67 "Weak: true, Warning: \'All fields populated!\' }\n"
68 "...\n";
69 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
70 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
71 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
72 EXPECT_NE(Stub.get(), nullptr);
73 EXPECT_TRUE(Stub->SoName.hasValue());
74 EXPECT_STREQ(Stub->SoName->c_str(), "test.so");
75 EXPECT_EQ(Stub->Symbols.size(), 5u);
77 auto Iterator = Stub->Symbols.begin();
78 ELFSymbol const &SymBar = *Iterator++;
79 EXPECT_STREQ(SymBar.Name.c_str(), "bar");
80 EXPECT_EQ(SymBar.Size, 42u);
81 EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
82 EXPECT_FALSE(SymBar.Undefined);
83 EXPECT_FALSE(SymBar.Weak);
84 EXPECT_FALSE(SymBar.Warning.hasValue());
86 ELFSymbol const &SymBaz = *Iterator++;
87 EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
88 EXPECT_EQ(SymBaz.Size, 3u);
89 EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
90 EXPECT_FALSE(SymBaz.Undefined);
91 EXPECT_FALSE(SymBaz.Weak);
92 EXPECT_FALSE(SymBaz.Warning.hasValue());
94 ELFSymbol const &SymFoo = *Iterator++;
95 EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
96 EXPECT_EQ(SymFoo.Size, 0u);
97 EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
98 EXPECT_FALSE(SymFoo.Undefined);
99 EXPECT_FALSE(SymFoo.Weak);
100 EXPECT_TRUE(SymFoo.Warning.hasValue());
101 EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
103 ELFSymbol const &SymNor = *Iterator++;
104 EXPECT_STREQ(SymNor.Name.c_str(), "nor");
105 EXPECT_EQ(SymNor.Size, 0u);
106 EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
107 EXPECT_TRUE(SymNor.Undefined);
108 EXPECT_FALSE(SymNor.Weak);
109 EXPECT_FALSE(SymNor.Warning.hasValue());
111 ELFSymbol const &SymNot = *Iterator++;
112 EXPECT_STREQ(SymNot.Name.c_str(), "not");
113 EXPECT_EQ(SymNot.Size, 111u);
114 EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
115 EXPECT_TRUE(SymNot.Undefined);
116 EXPECT_TRUE(SymNot.Weak);
117 EXPECT_TRUE(SymNot.Warning.hasValue());
118 EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");
121 TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
122 const char Data[] = "--- !tapi-tbe\n"
123 "TbeVersion: 1.0\n"
124 "SoName: test.so\n"
125 "Arch: x86_64\n"
126 "Symbols: {}\n"
127 "...\n";
128 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
129 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
130 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
131 EXPECT_NE(Stub.get(), nullptr);
132 EXPECT_EQ(0u, Stub->Symbols.size());
135 TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
136 // Can't read: wrong format/version.
137 const char Data[] = "--- !tapi-tbz\n"
138 "TbeVersion: z.3\n"
139 "SoName: test.so\n"
140 "Arch: x86_64\n"
141 "Symbols:\n"
142 " foo: { Type: Func, Undefined: true }\n";
143 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
144 ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed());
147 TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
148 const char Expected[] =
149 "--- !tapi-tbe\n"
150 "TbeVersion: 1.0\n"
151 "Arch: AArch64\n"
152 "Symbols:\n"
153 " bar: { Type: Func, Weak: true }\n"
154 " foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
155 " nor: { Type: Func, Undefined: true }\n"
156 " not: { Type: Unknown, Size: 12345678901234 }\n"
157 "...\n";
158 ELFStub Stub;
159 Stub.TbeVersion = VersionTuple(1, 0);
160 Stub.Arch = ELF::EM_AARCH64;
162 ELFSymbol SymFoo("foo");
163 SymFoo.Size = 99u;
164 SymFoo.Type = ELFSymbolType::NoType;
165 SymFoo.Undefined = false;
166 SymFoo.Weak = false;
167 SymFoo.Warning = "Does nothing";
169 ELFSymbol SymBar("bar");
170 SymBar.Size = 128u;
171 SymBar.Type = ELFSymbolType::Func;
172 SymBar.Undefined = false;
173 SymBar.Weak = true;
175 ELFSymbol SymNor("nor");
176 SymNor.Size = 1234u;
177 SymNor.Type = ELFSymbolType::Func;
178 SymNor.Undefined = true;
179 SymNor.Weak = false;
181 ELFSymbol SymNot("not");
182 SymNot.Size = 12345678901234u;
183 SymNot.Type = ELFSymbolType::Unknown;
184 SymNot.Undefined = false;
185 SymNot.Weak = false;
187 // Deliberately not in order to check that result is sorted.
188 Stub.Symbols.insert(SymNot);
189 Stub.Symbols.insert(SymBar);
190 Stub.Symbols.insert(SymFoo);
191 Stub.Symbols.insert(SymNor);
193 // Ensure move constructor works as expected.
194 ELFStub Moved = std::move(Stub);
196 std::string Result;
197 raw_string_ostream OS(Result);
198 ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Moved), Succeeded());
199 Result = OS.str();
200 compareByLine(Result.c_str(), Expected);
203 TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
204 const char Expected[] = "--- !tapi-tbe\n"
205 "TbeVersion: 1.0\n"
206 "SoName: nosyms.so\n"
207 "Arch: x86_64\n"
208 "NeededLibs:\n"
209 " - libc.so\n"
210 " - libfoo.so\n"
211 " - libbar.so\n"
212 "Symbols: {}\n"
213 "...\n";
214 ELFStub Stub;
215 Stub.TbeVersion = VersionTuple(1, 0);
216 Stub.SoName = "nosyms.so";
217 Stub.Arch = ELF::EM_X86_64;
218 Stub.NeededLibs.push_back("libc.so");
219 Stub.NeededLibs.push_back("libfoo.so");
220 Stub.NeededLibs.push_back("libbar.so");
222 std::string Result;
223 raw_string_ostream OS(Result);
224 ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Stub), Succeeded());
225 Result = OS.str();
226 compareByLine(Result.c_str(), Expected);