diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp b/contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp new file mode 100644 index 000000000000..ee95d21ee661 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp @@ -0,0 +1,143 @@ +//===- 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/InterfaceStub/TBEHandler.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/InterfaceStub/ELFStub.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/YAMLTraits.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 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"); + + if (Stub->TbeVersion > elfabi::TBEVersionCurrent) + return make_error<StringError>( + "TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.", + std::make_error_code(std::errc::invalid_argument)); + + 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(); +} |