summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/TextAPI/ELFYAMLTest.cpp
diff options
context:
space:
mode:
authorArmando Montanez <amontanez@google.com>2018-12-03 19:30:52 +0000
committerArmando Montanez <amontanez@google.com>2018-12-03 19:30:52 +0000
commit1e4b3709bb7d8a67a3382bf1e72364b0a9bd7429 (patch)
treef7b20de517b562360b7669b670e156d1dbc7875d /llvm/unittests/TextAPI/ELFYAMLTest.cpp
parent00f1d76738a50374019a47d30d09ee1829fe4a65 (diff)
downloadbcm5719-llvm-1e4b3709bb7d8a67a3382bf1e72364b0a9bd7429.tar.gz
bcm5719-llvm-1e4b3709bb7d8a67a3382bf1e72364b0a9bd7429.zip
[llvm-tapi] initial commit, supports ELF text stubs
http://lists.llvm.org/pipermail/llvm-dev/2018-September/126472.html TextAPI is a library and accompanying tool that allows conversion between binary shared object stubs and textual counterparts. The motivations and uses cases for this are explained thoroughly in the llvm-dev proposal [1]. This initial commit proposes a potential structure for the TAPI library, also including support for reading/writing text-based ELF stubs (.tbe) in addition to preliminary support for reading binary ELF files. The goal for this patch is to ensure the project architecture appropriately welcomes integration of Mach-O stubbing from Apple's TAPI [2]. Added: - TextAPI library - .tbe read support - .tbe write (to raw_ostream) support [1] http://lists.llvm.org/pipermail/llvm-dev/2018-September/126472.html [2] https://github.com/ributzka/tapi Differential Revision: https://reviews.llvm.org/D53051 llvm-svn: 348170
Diffstat (limited to 'llvm/unittests/TextAPI/ELFYAMLTest.cpp')
-rw-r--r--llvm/unittests/TextAPI/ELFYAMLTest.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/llvm/unittests/TextAPI/ELFYAMLTest.cpp b/llvm/unittests/TextAPI/ELFYAMLTest.cpp
new file mode 100644
index 00000000000..4616531de98
--- /dev/null
+++ b/llvm/unittests/TextAPI/ELFYAMLTest.cpp
@@ -0,0 +1,216 @@
+//===- llvm/unittests/TextAPI/YAMLTest.cpp --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TextAPI/ELF/ELFStub.h"
+#include "llvm/TextAPI/ELF/TBEHandler.h"
+#include "llvm/Support/Error.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::elfabi;
+
+std::unique_ptr<ELFStub> readFromBuffer(const char Data[]) {
+ TBEHandler Handler;
+
+ StringRef Buf(Data);
+
+ std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
+ EXPECT_NE(Stub.get(), nullptr);
+ return Stub;
+}
+
+void compareByLine(StringRef LHS, StringRef RHS) {
+ StringRef Line1;
+ StringRef Line2;
+ while (LHS.size() > 0 && RHS.size() > 0) {
+ std::tie(Line1, LHS) = LHS.split('\n');
+ std::tie(Line2, RHS) = RHS.split('\n');
+ // Comparing StringRef objects works, but has messy output when not equal.
+ // Using STREQ on StringRef.data() doesn't work since these substrings are
+ // not null terminated.
+ // This is inefficient, but forces null terminated strings that can be
+ // cleanly compared.
+ EXPECT_STREQ(Line1.str().data(), Line2.str().data());
+ }
+}
+
+TEST(ElfYamlTextAPI, YAMLReadableTBE) {
+ const char Data[] = "--- !tapi-tbe\n"
+ "TbeVersion: 1.0\n"
+ "SoName: test.so\n"
+ "Arch: x86_64\n"
+ "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
+ "Symbols:\n"
+ " foo: { Type: Func, Undefined: true }\n"
+ "...\n";
+ StringRef Buf = StringRef(Data);
+ TBEHandler Handler;
+ std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
+ EXPECT_NE(Stub.get(), nullptr);
+ EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
+ EXPECT_STREQ(Stub->SoName.c_str(), "test.so");
+ EXPECT_EQ(Stub->NeededLibs.size(), 3u);
+ EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
+ EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
+ EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");
+}
+
+TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
+ const char Data[] = "--- !tapi-tbe\n"
+ "TbeVersion: 1.0\n"
+ "SoName: test.so\n"
+ "Arch: x86_64\n"
+ "Symbols:\n"
+ " bar: { Type: Object, Size: 42 }\n"
+ " baz: { Type: TLS, Size: 3 }\n"
+ " foo: { Type: Func, Warning: \"Deprecated!\" }\n"
+ " nor: { Type: NoType, Undefined: true }\n"
+ " not: { Type: File, Undefined: true, Size: 111, "
+ "Warning: \'All fields populated!\' }\n"
+ "...\n";
+ std::unique_ptr<ELFStub> Stub = readFromBuffer(Data);
+ EXPECT_EQ(Stub->Symbols.size(), 5u);
+
+ auto Iterator = Stub->Symbols.begin();
+ ELFSymbol const &SymBar = *Iterator++;
+ EXPECT_STREQ(SymBar.Name.c_str(), "bar");
+ EXPECT_EQ(SymBar.Size, 42u);
+ EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
+ EXPECT_FALSE(SymBar.Undefined);
+ EXPECT_FALSE(SymBar.Warning.hasValue());
+
+ ELFSymbol const &SymBaz = *Iterator++;
+ EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
+ EXPECT_EQ(SymBaz.Size, 3u);
+ EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
+ EXPECT_FALSE(SymBaz.Undefined);
+ EXPECT_FALSE(SymBaz.Warning.hasValue());
+
+ ELFSymbol const &SymFoo = *Iterator++;
+ EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
+ EXPECT_EQ(SymFoo.Size, 0u);
+ EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
+ EXPECT_FALSE(SymFoo.Undefined);
+ EXPECT_TRUE(SymFoo.Warning.hasValue());
+ EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
+
+ ELFSymbol const &SymNor = *Iterator++;
+ EXPECT_STREQ(SymNor.Name.c_str(), "nor");
+ EXPECT_EQ(SymNor.Size, 0u);
+ EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
+ EXPECT_TRUE(SymNor.Undefined);
+ EXPECT_FALSE(SymNor.Warning.hasValue());
+
+ ELFSymbol const &SymNot = *Iterator++;
+ EXPECT_STREQ(SymNot.Name.c_str(), "not");
+ EXPECT_EQ(SymNot.Size, 111u);
+ EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
+ EXPECT_TRUE(SymNot.Undefined);
+ EXPECT_TRUE(SymNot.Warning.hasValue());
+ EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");
+}
+
+TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
+ const char Data[] = "--- !tapi-tbe\n"
+ "TbeVersion: 1.0\n"
+ "SoName: test.so\n"
+ "Arch: x86_64\n"
+ "Symbols: {}\n"
+ "...\n";
+ std::unique_ptr<ELFStub> Stub = readFromBuffer(Data);
+ EXPECT_EQ(0u, Stub->Symbols.size());
+}
+
+TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
+ TBEHandler Handler;
+ // Can't read: wrong format/version.
+ const char Data[] = "--- !tapi-tbz\n"
+ "TbeVersion: z.3\n"
+ "SoName: test.so\n"
+ "Arch: x86_64\n"
+ "Symbols:\n"
+ " foo: { Type: Func, Undefined: true }\n";
+ StringRef Buf = StringRef(Data);
+ std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
+ EXPECT_EQ(Stub.get(), nullptr);
+}
+
+TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
+ const char Expected[] =
+ "--- !tapi-tbe\n"
+ "TbeVersion: 1.0\n"
+ "SoName: test.so\n"
+ "Arch: AArch64\n"
+ "Symbols: \n"
+ " foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
+ " nor: { Type: Func, Undefined: true }\n"
+ " not: { Type: Unknown, Size: 12345678901234 }\n"
+ "...\n";
+ ELFStub Stub;
+ Stub.TbeVersion = VersionTuple(1, 0);
+ Stub.SoName = "test.so";
+ Stub.Arch = ELF::EM_AARCH64;
+
+ ELFSymbol SymFoo("foo");
+ SymFoo.Size = 99u;
+ SymFoo.Type = ELFSymbolType::NoType;
+ SymFoo.Undefined = false;
+ SymFoo.Warning = "Does nothing";
+
+ ELFSymbol SymNor("nor");
+ SymNor.Type = ELFSymbolType::Func;
+ SymNor.Undefined = true;
+
+ ELFSymbol SymNot("not");
+ SymNot.Size = 12345678901234u;
+ SymNot.Type = ELFSymbolType::Unknown;
+ SymNot.Undefined = false;
+
+ // Deliberately not in order to check that result is sorted.
+ Stub.Symbols.insert(SymNot);
+ Stub.Symbols.insert(SymFoo);
+ Stub.Symbols.insert(SymNor);
+
+ // Ensure move constructor works as expected.
+ ELFStub Moved = std::move(Stub);
+
+ std::string Result;
+ raw_string_ostream OS(Result);
+ TBEHandler Handler;
+ EXPECT_FALSE(Handler.writeFile(OS, Moved));
+ Result = OS.str();
+ compareByLine(Result.c_str(), Expected);
+}
+
+TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
+ const char Expected[] = "--- !tapi-tbe\n"
+ "TbeVersion: 1.0\n"
+ "SoName: nosyms.so\n"
+ "Arch: x86_64\n"
+ "NeededLibs: [ libc.so, libfoo.so, libbar.so ]\n"
+ "Symbols: {}\n"
+ "...\n";
+ ELFStub Stub;
+ Stub.TbeVersion = VersionTuple(1, 0);
+ Stub.SoName = "nosyms.so";
+ Stub.Arch = ELF::EM_X86_64;
+ Stub.NeededLibs.push_back("libc.so");
+ Stub.NeededLibs.push_back("libfoo.so");
+ Stub.NeededLibs.push_back("libbar.so");
+
+ std::string Result;
+ raw_string_ostream OS(Result);
+ TBEHandler Handler;
+ EXPECT_FALSE(Handler.writeFile(OS, Stub));
+ Result = OS.str();
+ compareByLine(Result.c_str(), Expected);
+}
OpenPOWER on IntegriCloud