TBEHandler.cpp revision 343171
1//===- TBEHandler.cpp -----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===-----------------------------------------------------------------------===/ 9 10#include "llvm/TextAPI/ELF/TBEHandler.h" 11#include "llvm/ADT/StringSwitch.h" 12#include "llvm/ADT/StringRef.h" 13#include "llvm/Support/Error.h" 14#include "llvm/Support/YAMLTraits.h" 15#include "llvm/TextAPI/ELF/ELFStub.h" 16 17using namespace llvm; 18using namespace llvm::elfabi; 19 20LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper) 21 22namespace llvm { 23namespace yaml { 24 25/// YAML traits for ELFSymbolType. 26template <> struct ScalarEnumerationTraits<ELFSymbolType> { 27 static void enumeration(IO &IO, ELFSymbolType &SymbolType) { 28 IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType); 29 IO.enumCase(SymbolType, "Func", ELFSymbolType::Func); 30 IO.enumCase(SymbolType, "Object", ELFSymbolType::Object); 31 IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS); 32 IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown); 33 // Treat other symbol types as noise, and map to Unknown. 34 if (!IO.outputting() && IO.matchEnumFallback()) 35 SymbolType = ELFSymbolType::Unknown; 36 } 37}; 38 39/// YAML traits for ELFArch. 40template <> struct ScalarTraits<ELFArchMapper> { 41 static void output(const ELFArchMapper &Value, void *, 42 llvm::raw_ostream &Out) { 43 // Map from integer to architecture string. 44 switch (Value) { 45 case (ELFArch)ELF::EM_X86_64: 46 Out << "x86_64"; 47 break; 48 case (ELFArch)ELF::EM_AARCH64: 49 Out << "AArch64"; 50 break; 51 case (ELFArch)ELF::EM_NONE: 52 default: 53 Out << "Unknown"; 54 } 55 } 56 57 static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) { 58 // Map from architecture string to integer. 59 Value = StringSwitch<ELFArch>(Scalar) 60 .Case("x86_64", ELF::EM_X86_64) 61 .Case("AArch64", ELF::EM_AARCH64) 62 .Case("Unknown", ELF::EM_NONE) 63 .Default(ELF::EM_NONE); 64 65 // Returning empty StringRef indicates successful parse. 66 return StringRef(); 67 } 68 69 // Don't place quotation marks around architecture value. 70 static QuotingType mustQuote(StringRef) { return QuotingType::None; } 71}; 72 73/// YAML traits for TbeVersion. 74template <> struct ScalarTraits<VersionTuple> { 75 static void output(const VersionTuple &Value, void *, 76 llvm::raw_ostream &Out) { 77 Out << Value.getAsString(); 78 } 79 80 static StringRef input(StringRef Scalar, void *, VersionTuple &Value) { 81 if (Value.tryParse(Scalar)) 82 return StringRef("Can't parse version: invalid version format."); 83 84 if (Value > TBEVersionCurrent) 85 return StringRef("Unsupported TBE version."); 86 87 // Returning empty StringRef indicates successful parse. 88 return StringRef(); 89 } 90 91 // Don't place quotation marks around version value. 92 static QuotingType mustQuote(StringRef) { return QuotingType::None; } 93}; 94 95/// YAML traits for ELFSymbol. 96template <> struct MappingTraits<ELFSymbol> { 97 static void mapping(IO &IO, ELFSymbol &Symbol) { 98 IO.mapRequired("Type", Symbol.Type); 99 // The need for symbol size depends on the symbol type. 100 if (Symbol.Type == ELFSymbolType::NoType) { 101 IO.mapOptional("Size", Symbol.Size, (uint64_t)0); 102 } else if (Symbol.Type == ELFSymbolType::Func) { 103 Symbol.Size = 0; 104 } else { 105 IO.mapRequired("Size", Symbol.Size); 106 } 107 IO.mapOptional("Undefined", Symbol.Undefined, false); 108 IO.mapOptional("Weak", Symbol.Weak, false); 109 IO.mapOptional("Warning", Symbol.Warning); 110 } 111 112 // Compacts symbol information into a single line. 113 static const bool flow = true; 114}; 115 116/// YAML traits for set of ELFSymbols. 117template <> struct CustomMappingTraits<std::set<ELFSymbol>> { 118 static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) { 119 ELFSymbol Sym(Key.str()); 120 IO.mapRequired(Key.str().c_str(), Sym); 121 Set.insert(Sym); 122 } 123 124 static void output(IO &IO, std::set<ELFSymbol> &Set) { 125 for (auto &Sym : Set) 126 IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym)); 127 } 128}; 129 130/// YAML traits for ELFStub objects. 131template <> struct MappingTraits<ELFStub> { 132 static void mapping(IO &IO, ELFStub &Stub) { 133 if (!IO.mapTag("!tapi-tbe", true)) 134 IO.setError("Not a .tbe YAML file."); 135 IO.mapRequired("TbeVersion", Stub.TbeVersion); 136 IO.mapOptional("SoName", Stub.SoName); 137 IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch); 138 IO.mapOptional("NeededLibs", Stub.NeededLibs); 139 IO.mapRequired("Symbols", Stub.Symbols); 140 } 141}; 142 143} // end namespace yaml 144} // end namespace llvm 145 146Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) { 147 yaml::Input YamlIn(Buf); 148 std::unique_ptr<ELFStub> Stub(new ELFStub()); 149 YamlIn >> *Stub; 150 if (std::error_code Err = YamlIn.error()) 151 return createStringError(Err, "YAML failed reading as TBE"); 152 153 return std::move(Stub); 154} 155 156Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) { 157 yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0); 158 159 YamlOut << const_cast<ELFStub &>(Stub); 160 return Error::success(); 161} 162