diff options
author | Armando Montanez <amontanez@google.com> | 2018-12-03 19:30:52 +0000 |
---|---|---|
committer | Armando Montanez <amontanez@google.com> | 2018-12-03 19:30:52 +0000 |
commit | 1e4b3709bb7d8a67a3382bf1e72364b0a9bd7429 (patch) | |
tree | f7b20de517b562360b7669b670e156d1dbc7875d /llvm/lib/TextAPI | |
parent | 00f1d76738a50374019a47d30d09ee1829fe4a65 (diff) | |
download | bcm5719-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/lib/TextAPI')
-rw-r--r-- | llvm/lib/TextAPI/CMakeLists.txt | 7 | ||||
-rw-r--r-- | llvm/lib/TextAPI/ELF/ELFStub.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/TextAPI/ELF/TBEHandler.cpp | 176 | ||||
-rw-r--r-- | llvm/lib/TextAPI/LLVMBuild.txt | 22 |
4 files changed, 234 insertions, 0 deletions
diff --git a/llvm/lib/TextAPI/CMakeLists.txt b/llvm/lib/TextAPI/CMakeLists.txt new file mode 100644 index 00000000000..7912e91fbf1 --- /dev/null +++ b/llvm/lib/TextAPI/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMTextAPI + ELF/ELFStub.cpp + ELF/TBEHandler.cpp + + ADDITIONAL_HEADER_DIRS + "${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI" +) diff --git a/llvm/lib/TextAPI/ELF/ELFStub.cpp b/llvm/lib/TextAPI/ELF/ELFStub.cpp new file mode 100644 index 00000000000..248a078a240 --- /dev/null +++ b/llvm/lib/TextAPI/ELF/ELFStub.cpp @@ -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); +} diff --git a/llvm/lib/TextAPI/ELF/TBEHandler.cpp b/llvm/lib/TextAPI/ELF/TBEHandler.cpp new file mode 100644 index 00000000000..f08a5b72fdd --- /dev/null +++ b/llvm/lib/TextAPI/ELF/TBEHandler.cpp @@ -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(); +} diff --git a/llvm/lib/TextAPI/LLVMBuild.txt b/llvm/lib/TextAPI/LLVMBuild.txt new file mode 100644 index 00000000000..83733a72f50 --- /dev/null +++ b/llvm/lib/TextAPI/LLVMBuild.txt @@ -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 |