]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/TextAPI/ELF/TBEHandler.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / TextAPI / ELF / TBEHandler.cpp
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
17 using namespace llvm;
18 using namespace llvm::elfabi;
19
20 LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)
21
22 namespace llvm {
23 namespace yaml {
24
25 /// YAML traits for ELFSymbolType.
26 template <> 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.
40 template <> 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.
74 template <> 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.
96 template <> 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.
117 template <> 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.
131 template <> 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
146 Expected<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
156 Error 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 }