-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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
- Loading branch information
1 parent
00f1d76
commit 1e4b370
Showing
11 changed files
with
575 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ subdirectories = | |
| ProfileData | ||
| Support | ||
| TableGen | ||
| TextAPI | ||
| Target | ||
| Testing | ||
| ToolDrivers | ||
|
|
||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| add_llvm_library(LLVMTextAPI | ||
| ELF/ELFStub.cpp | ||
| ELF/TBEHandler.cpp | ||
|
|
||
| ADDITIONAL_HEADER_DIRS | ||
| "${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI" | ||
| ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| set(LLVM_LINK_COMPONENTS | ||
| TextAPI | ||
| ) | ||
|
|
||
| add_llvm_unittest(TapiTests | ||
| ELFYAMLTest.cpp | ||
| ) |
Oops, something went wrong.