[llvm] r348170 - [llvm-tapi] initial commit, supports ELF text stubs
Armando Montanez via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 3 11:30:52 PST 2018
Author: amontanez
Date: Mon Dec 3 11:30:52 2018
New Revision: 348170
URL: http://llvm.org/viewvc/llvm-project?rev=348170&view=rev
Log:
[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
Added:
llvm/trunk/include/llvm/TextAPI/ELF/
llvm/trunk/include/llvm/TextAPI/ELF/ELFStub.h
llvm/trunk/include/llvm/TextAPI/ELF/TBEHandler.h
llvm/trunk/lib/TextAPI/CMakeLists.txt
llvm/trunk/lib/TextAPI/ELF/
llvm/trunk/lib/TextAPI/ELF/ELFStub.cpp
llvm/trunk/lib/TextAPI/ELF/TBEHandler.cpp
llvm/trunk/lib/TextAPI/LLVMBuild.txt
llvm/trunk/unittests/TextAPI/CMakeLists.txt
llvm/trunk/unittests/TextAPI/ELFYAMLTest.cpp
Modified:
llvm/trunk/lib/CMakeLists.txt
llvm/trunk/lib/LLVMBuild.txt
llvm/trunk/unittests/CMakeLists.txt
Added: llvm/trunk/include/llvm/TextAPI/ELF/ELFStub.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TextAPI/ELF/ELFStub.h?rev=348170&view=auto
==============================================================================
--- llvm/trunk/include/llvm/TextAPI/ELF/ELFStub.h (added)
+++ llvm/trunk/include/llvm/TextAPI/ELF/ELFStub.h Mon Dec 3 11:30:52 2018
@@ -0,0 +1,69 @@
+//===- ELFStub.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+///
+/// \file
+/// This file defines an internal representation of an ELF stub.
+///
+//===-----------------------------------------------------------------------===/
+
+#ifndef LLVM_TEXTAPI_ELF_ELFSTUB_H
+#define LLVM_TEXTAPI_ELF_ELFSTUB_H
+
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Support/VersionTuple.h"
+#include <vector>
+#include <set>
+
+namespace llvm {
+namespace elfabi {
+
+typedef uint16_t ELFArch;
+
+enum class ELFSymbolType {
+ NoType = ELF::STT_NOTYPE,
+ Object = ELF::STT_OBJECT,
+ Func = ELF::STT_FUNC,
+ TLS = ELF::STT_TLS,
+
+ // Type information is 4 bits, so 16 is safely out of range.
+ Unknown = 16,
+};
+
+struct ELFSymbol {
+ ELFSymbol(std::string SymbolName) : Name(SymbolName) {}
+ std::string Name;
+ uint64_t Size;
+ ELFSymbolType Type;
+ bool Undefined;
+ bool Weak;
+ Optional<std::string> Warning;
+ bool operator<(const ELFSymbol &RHS) const {
+ return Name < RHS.Name;
+ }
+};
+
+// A cumulative representation of ELF stubs.
+// Both textual and binary stubs will read into and write from this object.
+class ELFStub {
+// TODO: Add support for symbol versioning.
+public:
+ VersionTuple TbeVersion;
+ std::string SoName;
+ ELFArch Arch;
+ std::vector<std::string> NeededLibs;
+ std::set<ELFSymbol> Symbols;
+
+ ELFStub() {}
+ ELFStub(const ELFStub &Stub);
+ ELFStub(ELFStub &&Stub);
+};
+} // end namespace elfabi
+} // end namespace llvm
+
+#endif // LLVM_TEXTAPI_ELF_ELFSTUB_H
Added: llvm/trunk/include/llvm/TextAPI/ELF/TBEHandler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TextAPI/ELF/TBEHandler.h?rev=348170&view=auto
==============================================================================
--- llvm/trunk/include/llvm/TextAPI/ELF/TBEHandler.h (added)
+++ llvm/trunk/include/llvm/TextAPI/ELF/TBEHandler.h Mon Dec 3 11:30:52 2018
@@ -0,0 +1,46 @@
+//===- TBEHandler.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+///
+/// \file
+/// This file declares an interface for reading and writing .tbe (text-based
+/// ELF) files.
+///
+//===-----------------------------------------------------------------------===/
+
+#ifndef LLVM_TEXTAPI_ELF_TBEHANDLER_H
+#define LLVM_TEXTAPI_ELF_TBEHANDLER_H
+
+#include "llvm/Support/VersionTuple.h"
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+class Error;
+class StringRef;
+class VersionTuple;
+
+namespace elfabi {
+
+class ELFStub;
+
+const VersionTuple TBEVersionCurrent(1, 0);
+
+class TBEHandler {
+public:
+ /// Attempts to read an ELF interface file from a StringRef buffer.
+ std::unique_ptr<ELFStub> readFile(StringRef Buf);
+
+ /// Attempts to write an ELF interface file to a raw_ostream.
+ Error writeFile(raw_ostream &OS, const ELFStub &Stub);
+};
+} // end namespace elfabi
+} // end namespace llvm
+
+#endif // LLVM_TEXTAPI_ELF_TBEHANDLER_H
Modified: llvm/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=348170&r1=348169&r2=348170&view=diff
==============================================================================
--- llvm/trunk/lib/CMakeLists.txt (original)
+++ llvm/trunk/lib/CMakeLists.txt Mon Dec 3 11:30:52 2018
@@ -23,6 +23,7 @@ add_subdirectory(AsmParser)
add_subdirectory(LineEditor)
add_subdirectory(ProfileData)
add_subdirectory(Passes)
+add_subdirectory(TextAPI)
add_subdirectory(ToolDrivers)
add_subdirectory(XRay)
add_subdirectory(Testing)
Modified: llvm/trunk/lib/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LLVMBuild.txt?rev=348170&r1=348169&r2=348170&view=diff
==============================================================================
--- llvm/trunk/lib/LLVMBuild.txt (original)
+++ llvm/trunk/lib/LLVMBuild.txt Mon Dec 3 11:30:52 2018
@@ -40,6 +40,7 @@ subdirectories =
ProfileData
Support
TableGen
+ TextAPI
Target
Testing
ToolDrivers
Added: llvm/trunk/lib/TextAPI/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TextAPI/CMakeLists.txt?rev=348170&view=auto
==============================================================================
--- llvm/trunk/lib/TextAPI/CMakeLists.txt (added)
+++ llvm/trunk/lib/TextAPI/CMakeLists.txt Mon Dec 3 11:30:52 2018
@@ -0,0 +1,7 @@
+add_llvm_library(LLVMTextAPI
+ ELF/ELFStub.cpp
+ ELF/TBEHandler.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ "${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI"
+)
Added: llvm/trunk/lib/TextAPI/ELF/ELFStub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TextAPI/ELF/ELFStub.cpp?rev=348170&view=auto
==============================================================================
--- llvm/trunk/lib/TextAPI/ELF/ELFStub.cpp (added)
+++ llvm/trunk/lib/TextAPI/ELF/ELFStub.cpp Mon Dec 3 11:30:52 2018
@@ -0,0 +1,29 @@
+//===- ELFStub.cpp --------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+
+#include "llvm/TextAPI/ELF/ELFStub.h"
+
+using namespace llvm;
+using namespace llvm::elfabi;
+
+ELFStub::ELFStub(ELFStub const &Stub) {
+ TbeVersion = Stub.TbeVersion;
+ Arch = Stub.Arch;
+ SoName = Stub.SoName;
+ NeededLibs = Stub.NeededLibs;
+ Symbols = Stub.Symbols;
+}
+
+ELFStub::ELFStub(ELFStub &&Stub) {
+ TbeVersion = std::move(Stub.TbeVersion);
+ Arch = std::move(Stub.Arch);
+ SoName = std::move(Stub.SoName);
+ NeededLibs = std::move(Stub.NeededLibs);
+ Symbols = std::move(Stub.Symbols);
+}
Added: llvm/trunk/lib/TextAPI/ELF/TBEHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TextAPI/ELF/TBEHandler.cpp?rev=348170&view=auto
==============================================================================
--- llvm/trunk/lib/TextAPI/ELF/TBEHandler.cpp (added)
+++ llvm/trunk/lib/TextAPI/ELF/TBEHandler.cpp Mon Dec 3 11:30:52 2018
@@ -0,0 +1,176 @@
+//===- TBEHandler.cpp -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+
+#include "llvm/TextAPI/ELF/TBEHandler.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/TextAPI/ELF/ELFStub.h"
+
+using namespace llvm;
+using namespace llvm::elfabi;
+
+LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper);
+
+namespace llvm {
+namespace yaml {
+
+/// YAML traits for ELFSymbolType.
+template <> struct ScalarEnumerationTraits<ELFSymbolType> {
+ static void enumeration(IO &IO, ELFSymbolType &SymbolType) {
+ IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType);
+ IO.enumCase(SymbolType, "Func", ELFSymbolType::Func);
+ IO.enumCase(SymbolType, "Object", ELFSymbolType::Object);
+ IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS);
+ IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown);
+ // Treat other symbol types as noise, and map to Unknown.
+ if (!IO.outputting() && IO.matchEnumFallback())
+ SymbolType = ELFSymbolType::Unknown;
+ }
+};
+
+/// YAML traits for ELFArch.
+template <> struct ScalarTraits<ELFArchMapper> {
+ static void output(const ELFArchMapper &Value, void *,
+ llvm::raw_ostream &Out) {
+ // Map from integer to architecture string.
+ switch (Value) {
+ case (ELFArch)ELF::EM_X86_64:
+ Out << "x86_64";
+ break;
+ case (ELFArch)ELF::EM_AARCH64:
+ Out << "AArch64";
+ break;
+ case (ELFArch)ELF::EM_NONE:
+ default:
+ Out << "Unknown";
+ }
+ }
+
+ static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) {
+ // Map from architecture string to integer.
+ Value = StringSwitch<ELFArch>(Scalar)
+ .Case("x86_64", ELF::EM_X86_64)
+ .Case("AArch64", ELF::EM_AARCH64)
+ .Case("Unknown", ELF::EM_NONE)
+ .Default(ELF::EM_NONE);
+
+ // Returning empty StringRef indicates successful parse.
+ return StringRef();
+ }
+
+ // Don't place quotation marks around architecture value.
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+/// YAML traits for TbeVersion.
+template <> struct ScalarTraits<VersionTuple> {
+ static void output(const VersionTuple &Value, void *,
+ llvm::raw_ostream &Out) {
+ Out << Value.getAsString();
+ }
+
+ static StringRef input(StringRef Scalar, void *, VersionTuple &Value) {
+ if (Value.tryParse(Scalar))
+ return StringRef("Can't parse version: invalid version format.");
+
+ if (Value > TBEVersionCurrent)
+ return StringRef("Unsupported TBE version.");
+
+ // Returning empty StringRef indicates successful parse.
+ return StringRef();
+ }
+
+ // Don't place quotation marks around version value.
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+/// YAML traits for ELFSymbol.
+template <> struct MappingTraits<ELFSymbol> {
+ static void mapping(IO &IO, ELFSymbol &Symbol) {
+ IO.mapRequired("Type", Symbol.Type);
+ // The need for symbol size depends on the symbol type.
+ if (Symbol.Type == ELFSymbolType::NoType) {
+ IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
+ } else if (Symbol.Type == ELFSymbolType::Func) {
+ Symbol.Size = 0;
+ } else {
+ IO.mapRequired("Size", Symbol.Size);
+ }
+ IO.mapOptional("Undefined", Symbol.Undefined, false);
+ IO.mapOptional("Warning", Symbol.Warning);
+ }
+
+ // Compacts symbol information into a single line.
+ static const bool flow = true;
+};
+
+/// YAML traits for set of ELFSymbols.
+template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
+ static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
+ ELFSymbol Sym(Key.str());
+ IO.mapRequired(Key.str().c_str(), Sym);
+ Set.insert(Sym);
+ }
+
+ static void output(IO &IO, std::set<ELFSymbol> &Set) {
+ for (auto &Sym : Set)
+ IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
+ }
+};
+
+/// YAML traits for generic string vectors (i.e. list of needed libraries).
+template <> struct SequenceTraits<std::vector<std::string>> {
+ static size_t size(IO &IO, std::vector<std::string> &List) {
+ return List.size();
+ }
+
+ static std::string &element(IO &IO, std::vector<std::string> &List,
+ size_t Index) {
+ if (Index >= List.size())
+ List.resize(Index + 1);
+ return List[Index];
+ }
+
+ // Compacts list of needed libraries into a single line.
+ static const bool flow = true;
+};
+
+/// YAML traits for ELFStub objects.
+template <> struct MappingTraits<ELFStub> {
+ static void mapping(IO &IO, ELFStub &Stub) {
+ if (!IO.mapTag("!tapi-tbe", true))
+ IO.setError("Not a .tbe YAML file.");
+ IO.mapRequired("TbeVersion", Stub.TbeVersion);
+ IO.mapRequired("SoName", Stub.SoName);
+ IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
+ IO.mapOptional("NeededLibs", Stub.NeededLibs);
+ IO.mapRequired("Symbols", Stub.Symbols);
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+std::unique_ptr<ELFStub> TBEHandler::readFile(StringRef Buf) {
+ yaml::Input YamlIn(Buf);
+ std::unique_ptr<ELFStub> Stub(new ELFStub());
+ YamlIn >> *Stub;
+ if (YamlIn.error())
+ return nullptr;
+ return Stub;
+}
+
+Error TBEHandler::writeFile(raw_ostream &OS, const ELFStub &Stub) {
+ yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
+
+ YamlOut << const_cast<ELFStub &>(Stub);
+ return Error::success();
+}
Added: llvm/trunk/lib/TextAPI/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TextAPI/LLVMBuild.txt?rev=348170&view=auto
==============================================================================
--- llvm/trunk/lib/TextAPI/LLVMBuild.txt (added)
+++ llvm/trunk/lib/TextAPI/LLVMBuild.txt Mon Dec 3 11:30:52 2018
@@ -0,0 +1,22 @@
+;===- ./lib/TextAPI/LLVMBuild.txt ------------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = TextAPI
+parent = Libraries
+required_libraries = Support BinaryFormat
Modified: llvm/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=348170&r1=348169&r2=348170&view=diff
==============================================================================
--- llvm/trunk/unittests/CMakeLists.txt (original)
+++ llvm/trunk/unittests/CMakeLists.txt Mon Dec 3 11:30:52 2018
@@ -30,6 +30,7 @@ add_subdirectory(OptRemarks)
add_subdirectory(Passes)
add_subdirectory(ProfileData)
add_subdirectory(Support)
+add_subdirectory(TextAPI)
add_subdirectory(Target)
add_subdirectory(Transforms)
add_subdirectory(XRay)
Added: llvm/trunk/unittests/TextAPI/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/TextAPI/CMakeLists.txt?rev=348170&view=auto
==============================================================================
--- llvm/trunk/unittests/TextAPI/CMakeLists.txt (added)
+++ llvm/trunk/unittests/TextAPI/CMakeLists.txt Mon Dec 3 11:30:52 2018
@@ -0,0 +1,7 @@
+set(LLVM_LINK_COMPONENTS
+ TextAPI
+)
+
+add_llvm_unittest(TapiTests
+ ELFYAMLTest.cpp
+)
Added: llvm/trunk/unittests/TextAPI/ELFYAMLTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/TextAPI/ELFYAMLTest.cpp?rev=348170&view=auto
==============================================================================
--- llvm/trunk/unittests/TextAPI/ELFYAMLTest.cpp (added)
+++ llvm/trunk/unittests/TextAPI/ELFYAMLTest.cpp Mon Dec 3 11:30:52 2018
@@ -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);
+}
More information about the llvm-commits
mailing list