blob: a321666372988427b688ee43cf8f0c78a2031321 [file] [log] [blame]
Armando Montanez1e4b3702018-12-03 19:30:52 +00001//===- 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
Martin Storsjoa79303d2018-12-03 20:02:15 +000020LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)
Armando Montanez1e4b3702018-12-03 19:30:52 +000021
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("Warning", Symbol.Warning);
109 }
110
111 // Compacts symbol information into a single line.
112 static const bool flow = true;
113};
114
115/// YAML traits for set of ELFSymbols.
116template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
117 static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
118 ELFSymbol Sym(Key.str());
119 IO.mapRequired(Key.str().c_str(), Sym);
120 Set.insert(Sym);
121 }
122
123 static void output(IO &IO, std::set<ELFSymbol> &Set) {
124 for (auto &Sym : Set)
125 IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
126 }
127};
128
Armando Montanezc9488e42018-12-07 01:31:28 +0000129/// YAML traits for generic string vectors (i.e. list of needed libraries).
130template <> struct SequenceTraits<std::vector<std::string>> {
131 static size_t size(IO &IO, std::vector<std::string> &List) {
132 return List.size();
Armando Montanez1e4b3702018-12-03 19:30:52 +0000133 }
134
Armando Montanezc9488e42018-12-07 01:31:28 +0000135 static std::string &element(IO &IO, std::vector<std::string> &List,
136 size_t Index) {
137 if (Index >= List.size())
138 List.resize(Index + 1);
139 return List[Index];
Armando Montanez1e4b3702018-12-03 19:30:52 +0000140 }
141
Armando Montanezc9488e42018-12-07 01:31:28 +0000142 // Compacts list of needed libraries into a single line.
143 static const bool flow = true;
Armando Montanez1e4b3702018-12-03 19:30:52 +0000144};
145
146/// YAML traits for ELFStub objects.
147template <> struct MappingTraits<ELFStub> {
148 static void mapping(IO &IO, ELFStub &Stub) {
149 if (!IO.mapTag("!tapi-tbe", true))
150 IO.setError("Not a .tbe YAML file.");
151 IO.mapRequired("TbeVersion", Stub.TbeVersion);
152 IO.mapRequired("SoName", Stub.SoName);
153 IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
Armando Montanezc9488e42018-12-07 01:31:28 +0000154 IO.mapOptional("NeededLibs", Stub.NeededLibs);
Armando Montanez1e4b3702018-12-03 19:30:52 +0000155 IO.mapRequired("Symbols", Stub.Symbols);
156 }
157};
158
159} // end namespace yaml
160} // end namespace llvm
161
162std::unique_ptr<ELFStub> TBEHandler::readFile(StringRef Buf) {
163 yaml::Input YamlIn(Buf);
164 std::unique_ptr<ELFStub> Stub(new ELFStub());
165 YamlIn >> *Stub;
166 if (YamlIn.error())
167 return nullptr;
168 return Stub;
169}
170
171Error TBEHandler::writeFile(raw_ostream &OS, const ELFStub &Stub) {
172 yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
173
174 YamlOut << const_cast<ELFStub &>(Stub);
175 return Error::success();
176}