diff options
Diffstat (limited to 'llvm/lib/TextAPI/ELF')
| -rw-r--r-- | llvm/lib/TextAPI/ELF/ELFStub.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/TextAPI/ELF/TBEHandler.cpp | 160 | 
2 files changed, 188 insertions, 0 deletions
| diff --git a/llvm/lib/TextAPI/ELF/ELFStub.cpp b/llvm/lib/TextAPI/ELF/ELFStub.cpp new file mode 100644 index 000000000000..f8463497093b --- /dev/null +++ b/llvm/lib/TextAPI/ELF/ELFStub.cpp @@ -0,0 +1,28 @@ +//===- ELFStub.cpp --------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===-----------------------------------------------------------------------===/ + +#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 000000000000..cb597d8896e8 --- /dev/null +++ b/llvm/lib/TextAPI/ELF/TBEHandler.cpp @@ -0,0 +1,160 @@ +//===- TBEHandler.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===-----------------------------------------------------------------------===/ + +#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("Weak", Symbol.Weak, 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 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.mapOptional("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 + +Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) { +  yaml::Input YamlIn(Buf); +  std::unique_ptr<ELFStub> Stub(new ELFStub()); +  YamlIn >> *Stub; +  if (std::error_code Err = YamlIn.error()) +    return createStringError(Err, "YAML failed reading as TBE"); + +  return std::move(Stub); +} + +Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) { +  yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0); + +  YamlOut << const_cast<ELFStub &>(Stub); +  return Error::success(); +} | 
