blob: 1ace819cab620a8d3ba9dea34f3331f01fa81487 [file] [log] [blame]
Armando Montanezbab257c2018-12-03 19:30:52 +00001//===- llvm/unittests/TextAPI/YAMLTest.cpp --------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===-----------------------------------------------------------------------===/
9
10#include "llvm/ADT/StringRef.h"
11#include "llvm/TextAPI/ELF/ELFStub.h"
12#include "llvm/TextAPI/ELF/TBEHandler.h"
13#include "llvm/Support/Error.h"
Armando Montanez01342482018-12-10 02:36:33 +000014#include "llvm/Testing/Support/Error.h"
Armando Montanezbab257c2018-12-03 19:30:52 +000015#include "gtest/gtest.h"
16#include <string>
17
18using namespace llvm;
19using namespace llvm::ELF;
20using namespace llvm::elfabi;
21
Armando Montanezbab257c2018-12-03 19:30:52 +000022void compareByLine(StringRef LHS, StringRef RHS) {
23 StringRef Line1;
24 StringRef Line2;
25 while (LHS.size() > 0 && RHS.size() > 0) {
26 std::tie(Line1, LHS) = LHS.split('\n');
27 std::tie(Line2, RHS) = RHS.split('\n');
28 // Comparing StringRef objects works, but has messy output when not equal.
29 // Using STREQ on StringRef.data() doesn't work since these substrings are
30 // not null terminated.
31 // This is inefficient, but forces null terminated strings that can be
32 // cleanly compared.
33 EXPECT_STREQ(Line1.str().data(), Line2.str().data());
34 }
35}
36
37TEST(ElfYamlTextAPI, YAMLReadableTBE) {
38 const char Data[] = "--- !tapi-tbe\n"
39 "TbeVersion: 1.0\n"
Armando Montanezbab257c2018-12-03 19:30:52 +000040 "Arch: x86_64\n"
41 "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
42 "Symbols:\n"
43 " foo: { Type: Func, Undefined: true }\n"
44 "...\n";
Armando Montanez01342482018-12-10 02:36:33 +000045 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
46 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
47 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
Armando Montanezbab257c2018-12-03 19:30:52 +000048 EXPECT_NE(Stub.get(), nullptr);
Armando Montanez06657362018-12-11 01:00:16 +000049 EXPECT_FALSE(Stub->SoName.hasValue());
Armando Montanezbab257c2018-12-03 19:30:52 +000050 EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
Armando Montanezbab257c2018-12-03 19:30:52 +000051 EXPECT_EQ(Stub->NeededLibs.size(), 3u);
52 EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
53 EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
54 EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");
55}
56
57TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
58 const char Data[] = "--- !tapi-tbe\n"
59 "TbeVersion: 1.0\n"
60 "SoName: test.so\n"
61 "Arch: x86_64\n"
62 "Symbols:\n"
63 " bar: { Type: Object, Size: 42 }\n"
64 " baz: { Type: TLS, Size: 3 }\n"
65 " foo: { Type: Func, Warning: \"Deprecated!\" }\n"
66 " nor: { Type: NoType, Undefined: true }\n"
67 " not: { Type: File, Undefined: true, Size: 111, "
Armando Montanezec2e0f92018-12-21 20:45:58 +000068 "Weak: true, Warning: \'All fields populated!\' }\n"
Armando Montanezbab257c2018-12-03 19:30:52 +000069 "...\n";
Armando Montanez01342482018-12-10 02:36:33 +000070 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
71 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
72 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
73 EXPECT_NE(Stub.get(), nullptr);
Armando Montanez06657362018-12-11 01:00:16 +000074 EXPECT_TRUE(Stub->SoName.hasValue());
75 EXPECT_STREQ(Stub->SoName->c_str(), "test.so");
Armando Montanezbab257c2018-12-03 19:30:52 +000076 EXPECT_EQ(Stub->Symbols.size(), 5u);
77
78 auto Iterator = Stub->Symbols.begin();
79 ELFSymbol const &SymBar = *Iterator++;
80 EXPECT_STREQ(SymBar.Name.c_str(), "bar");
81 EXPECT_EQ(SymBar.Size, 42u);
82 EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
83 EXPECT_FALSE(SymBar.Undefined);
Armando Montanezec2e0f92018-12-21 20:45:58 +000084 EXPECT_FALSE(SymBar.Weak);
Armando Montanezbab257c2018-12-03 19:30:52 +000085 EXPECT_FALSE(SymBar.Warning.hasValue());
86
87 ELFSymbol const &SymBaz = *Iterator++;
88 EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
89 EXPECT_EQ(SymBaz.Size, 3u);
90 EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
91 EXPECT_FALSE(SymBaz.Undefined);
Armando Montanezec2e0f92018-12-21 20:45:58 +000092 EXPECT_FALSE(SymBaz.Weak);
Armando Montanezbab257c2018-12-03 19:30:52 +000093 EXPECT_FALSE(SymBaz.Warning.hasValue());
94
95 ELFSymbol const &SymFoo = *Iterator++;
96 EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
97 EXPECT_EQ(SymFoo.Size, 0u);
98 EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
99 EXPECT_FALSE(SymFoo.Undefined);
Armando Montanezec2e0f92018-12-21 20:45:58 +0000100 EXPECT_FALSE(SymFoo.Weak);
Armando Montanezbab257c2018-12-03 19:30:52 +0000101 EXPECT_TRUE(SymFoo.Warning.hasValue());
102 EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
103
104 ELFSymbol const &SymNor = *Iterator++;
105 EXPECT_STREQ(SymNor.Name.c_str(), "nor");
106 EXPECT_EQ(SymNor.Size, 0u);
107 EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
108 EXPECT_TRUE(SymNor.Undefined);
Armando Montanezec2e0f92018-12-21 20:45:58 +0000109 EXPECT_FALSE(SymNor.Weak);
Armando Montanezbab257c2018-12-03 19:30:52 +0000110 EXPECT_FALSE(SymNor.Warning.hasValue());
111
112 ELFSymbol const &SymNot = *Iterator++;
113 EXPECT_STREQ(SymNot.Name.c_str(), "not");
114 EXPECT_EQ(SymNot.Size, 111u);
115 EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
116 EXPECT_TRUE(SymNot.Undefined);
Armando Montanezec2e0f92018-12-21 20:45:58 +0000117 EXPECT_TRUE(SymNot.Weak);
Armando Montanezbab257c2018-12-03 19:30:52 +0000118 EXPECT_TRUE(SymNot.Warning.hasValue());
119 EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");
120}
121
122TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
123 const char Data[] = "--- !tapi-tbe\n"
124 "TbeVersion: 1.0\n"
125 "SoName: test.so\n"
126 "Arch: x86_64\n"
127 "Symbols: {}\n"
128 "...\n";
Armando Montanez01342482018-12-10 02:36:33 +0000129 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
130 ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
131 std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
132 EXPECT_NE(Stub.get(), nullptr);
Armando Montanezbab257c2018-12-03 19:30:52 +0000133 EXPECT_EQ(0u, Stub->Symbols.size());
134}
135
136TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
Armando Montanezbab257c2018-12-03 19:30:52 +0000137 // Can't read: wrong format/version.
138 const char Data[] = "--- !tapi-tbz\n"
139 "TbeVersion: z.3\n"
140 "SoName: test.so\n"
141 "Arch: x86_64\n"
142 "Symbols:\n"
143 " foo: { Type: Func, Undefined: true }\n";
Armando Montanez01342482018-12-10 02:36:33 +0000144 Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
145 ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed());
Armando Montanezbab257c2018-12-03 19:30:52 +0000146}
147
148TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
149 const char Expected[] =
150 "--- !tapi-tbe\n"
151 "TbeVersion: 1.0\n"
Armando Montanezbab257c2018-12-03 19:30:52 +0000152 "Arch: AArch64\n"
153 "Symbols: \n"
Armando Montanezec2e0f92018-12-21 20:45:58 +0000154 " bar: { Type: Func, Weak: true }\n"
Armando Montanezbab257c2018-12-03 19:30:52 +0000155 " foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
156 " nor: { Type: Func, Undefined: true }\n"
157 " not: { Type: Unknown, Size: 12345678901234 }\n"
158 "...\n";
159 ELFStub Stub;
160 Stub.TbeVersion = VersionTuple(1, 0);
Armando Montanezbab257c2018-12-03 19:30:52 +0000161 Stub.Arch = ELF::EM_AARCH64;
162
163 ELFSymbol SymFoo("foo");
164 SymFoo.Size = 99u;
165 SymFoo.Type = ELFSymbolType::NoType;
166 SymFoo.Undefined = false;
Armando Montanezec2e0f92018-12-21 20:45:58 +0000167 SymFoo.Weak = false;
Armando Montanezbab257c2018-12-03 19:30:52 +0000168 SymFoo.Warning = "Does nothing";
169
Armando Montanezec2e0f92018-12-21 20:45:58 +0000170 ELFSymbol SymBar("bar");
171 SymBar.Size = 128u;
172 SymBar.Type = ELFSymbolType::Func;
Armando Montanez3995aa62018-12-21 21:44:09 +0000173 SymBar.Undefined = false;
Armando Montanezec2e0f92018-12-21 20:45:58 +0000174 SymBar.Weak = true;
175
Armando Montanezbab257c2018-12-03 19:30:52 +0000176 ELFSymbol SymNor("nor");
Armando Montanez3995aa62018-12-21 21:44:09 +0000177 SymNor.Size = 1234u;
Armando Montanezbab257c2018-12-03 19:30:52 +0000178 SymNor.Type = ELFSymbolType::Func;
179 SymNor.Undefined = true;
Armando Montanezec2e0f92018-12-21 20:45:58 +0000180 SymNor.Weak = false;
Armando Montanezbab257c2018-12-03 19:30:52 +0000181
182 ELFSymbol SymNot("not");
183 SymNot.Size = 12345678901234u;
184 SymNot.Type = ELFSymbolType::Unknown;
185 SymNot.Undefined = false;
Armando Montanezec2e0f92018-12-21 20:45:58 +0000186 SymNot.Weak = false;
Armando Montanezbab257c2018-12-03 19:30:52 +0000187
188 // Deliberately not in order to check that result is sorted.
189 Stub.Symbols.insert(SymNot);
Armando Montanezec2e0f92018-12-21 20:45:58 +0000190 Stub.Symbols.insert(SymBar);
Armando Montanezbab257c2018-12-03 19:30:52 +0000191 Stub.Symbols.insert(SymFoo);
192 Stub.Symbols.insert(SymNor);
193
194 // Ensure move constructor works as expected.
195 ELFStub Moved = std::move(Stub);
196
197 std::string Result;
198 raw_string_ostream OS(Result);
Armando Montanez01342482018-12-10 02:36:33 +0000199 ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Moved), Succeeded());
Armando Montanezbab257c2018-12-03 19:30:52 +0000200 Result = OS.str();
201 compareByLine(Result.c_str(), Expected);
202}
203
204TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
205 const char Expected[] = "--- !tapi-tbe\n"
206 "TbeVersion: 1.0\n"
207 "SoName: nosyms.so\n"
208 "Arch: x86_64\n"
Sam Clegga97d9f82018-12-07 19:29:00 +0000209 "NeededLibs: \n"
210 " - libc.so\n"
211 " - libfoo.so\n"
212 " - libbar.so\n"
Armando Montanezbab257c2018-12-03 19:30:52 +0000213 "Symbols: {}\n"
214 "...\n";
215 ELFStub Stub;
216 Stub.TbeVersion = VersionTuple(1, 0);
217 Stub.SoName = "nosyms.so";
218 Stub.Arch = ELF::EM_X86_64;
219 Stub.NeededLibs.push_back("libc.so");
220 Stub.NeededLibs.push_back("libfoo.so");
221 Stub.NeededLibs.push_back("libbar.so");
222
223 std::string Result;
224 raw_string_ostream OS(Result);
Armando Montanez01342482018-12-10 02:36:33 +0000225 ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Stub), Succeeded());
Armando Montanezbab257c2018-12-03 19:30:52 +0000226 Result = OS.str();
227 compareByLine(Result.c_str(), Expected);
228}