blob: ee95d21ee6618b7592ac1dca80bf179ee8ec7146 [file] [log] [blame]
Armando Montanez1e4b3702018-12-03 19:30:52 +00001//===- TBEHandler.cpp -----------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Armando Montanez1e4b3702018-12-03 19:30:52 +00006//
7//===-----------------------------------------------------------------------===/
8
Haowei Wud650cbc2020-08-11 11:44:22 -07009#include "llvm/InterfaceStub/TBEHandler.h"
Armando Montanez1e4b3702018-12-03 19:30:52 +000010#include "llvm/ADT/StringRef.h"
Haowei Wud650cbc2020-08-11 11:44:22 -070011#include "llvm/ADT/StringSwitch.h"
12#include "llvm/InterfaceStub/ELFStub.h"
Armando Montanez1e4b3702018-12-03 19:30:52 +000013#include "llvm/Support/Error.h"
14#include "llvm/Support/YAMLTraits.h"
Armando Montanez1e4b3702018-12-03 19:30:52 +000015
16using namespace llvm;
17using namespace llvm::elfabi;
18
Martin Storsjoa79303d2018-12-03 20:02:15 +000019LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)
Armando Montanez1e4b3702018-12-03 19:30:52 +000020
21namespace llvm {
22namespace yaml {
23
24/// YAML traits for ELFSymbolType.
25template <> struct ScalarEnumerationTraits<ELFSymbolType> {
26 static void enumeration(IO &IO, ELFSymbolType &SymbolType) {
27 IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType);
28 IO.enumCase(SymbolType, "Func", ELFSymbolType::Func);
29 IO.enumCase(SymbolType, "Object", ELFSymbolType::Object);
30 IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS);
31 IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown);
32 // Treat other symbol types as noise, and map to Unknown.
33 if (!IO.outputting() && IO.matchEnumFallback())
34 SymbolType = ELFSymbolType::Unknown;
35 }
36};
37
38/// YAML traits for ELFArch.
39template <> struct ScalarTraits<ELFArchMapper> {
40 static void output(const ELFArchMapper &Value, void *,
41 llvm::raw_ostream &Out) {
42 // Map from integer to architecture string.
43 switch (Value) {
44 case (ELFArch)ELF::EM_X86_64:
45 Out << "x86_64";
46 break;
47 case (ELFArch)ELF::EM_AARCH64:
48 Out << "AArch64";
49 break;
50 case (ELFArch)ELF::EM_NONE:
51 default:
52 Out << "Unknown";
53 }
54 }
55
56 static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) {
57 // Map from architecture string to integer.
58 Value = StringSwitch<ELFArch>(Scalar)
59 .Case("x86_64", ELF::EM_X86_64)
60 .Case("AArch64", ELF::EM_AARCH64)
61 .Case("Unknown", ELF::EM_NONE)
62 .Default(ELF::EM_NONE);
63
64 // Returning empty StringRef indicates successful parse.
65 return StringRef();
66 }
67
68 // Don't place quotation marks around architecture value.
69 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
70};
71
Armando Montanez1e4b3702018-12-03 19:30:52 +000072/// YAML traits for ELFSymbol.
73template <> struct MappingTraits<ELFSymbol> {
74 static void mapping(IO &IO, ELFSymbol &Symbol) {
75 IO.mapRequired("Type", Symbol.Type);
76 // The need for symbol size depends on the symbol type.
77 if (Symbol.Type == ELFSymbolType::NoType) {
78 IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
79 } else if (Symbol.Type == ELFSymbolType::Func) {
80 Symbol.Size = 0;
81 } else {
82 IO.mapRequired("Size", Symbol.Size);
83 }
84 IO.mapOptional("Undefined", Symbol.Undefined, false);
Armando Montanez4cc21132018-12-21 20:45:58 +000085 IO.mapOptional("Weak", Symbol.Weak, false);
Armando Montanez1e4b3702018-12-03 19:30:52 +000086 IO.mapOptional("Warning", Symbol.Warning);
87 }
88
89 // Compacts symbol information into a single line.
90 static const bool flow = true;
91};
92
93/// YAML traits for set of ELFSymbols.
94template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
95 static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
96 ELFSymbol Sym(Key.str());
97 IO.mapRequired(Key.str().c_str(), Sym);
98 Set.insert(Sym);
99 }
100
101 static void output(IO &IO, std::set<ELFSymbol> &Set) {
102 for (auto &Sym : Set)
103 IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
104 }
105};
106
Armando Montanez1e4b3702018-12-03 19:30:52 +0000107/// YAML traits for ELFStub objects.
108template <> struct MappingTraits<ELFStub> {
109 static void mapping(IO &IO, ELFStub &Stub) {
110 if (!IO.mapTag("!tapi-tbe", true))
111 IO.setError("Not a .tbe YAML file.");
112 IO.mapRequired("TbeVersion", Stub.TbeVersion);
Armando Montanez6d6ff2e2018-12-11 01:00:16 +0000113 IO.mapOptional("SoName", Stub.SoName);
Armando Montanez1e4b3702018-12-03 19:30:52 +0000114 IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
Armando Montanezc9488e42018-12-07 01:31:28 +0000115 IO.mapOptional("NeededLibs", Stub.NeededLibs);
Armando Montanez1e4b3702018-12-03 19:30:52 +0000116 IO.mapRequired("Symbols", Stub.Symbols);
117 }
118};
119
120} // end namespace yaml
121} // end namespace llvm
122
Armando Montaneze3534592018-12-10 02:36:33 +0000123Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) {
Armando Montanez1e4b3702018-12-03 19:30:52 +0000124 yaml::Input YamlIn(Buf);
125 std::unique_ptr<ELFStub> Stub(new ELFStub());
126 YamlIn >> *Stub;
Armando Montaneze3534592018-12-10 02:36:33 +0000127 if (std::error_code Err = YamlIn.error())
128 return createStringError(Err, "YAML failed reading as TBE");
129
Cyndy Ishidaacb33cb2020-10-20 17:50:29 -0700130 if (Stub->TbeVersion > elfabi::TBEVersionCurrent)
131 return make_error<StringError>(
132 "TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.",
133 std::make_error_code(std::errc::invalid_argument));
134
Bill Wendlingc55cf4a2020-02-10 07:06:45 -0800135 return std::move(Stub);
Armando Montanez1e4b3702018-12-03 19:30:52 +0000136}
137
Armando Montaneze3534592018-12-10 02:36:33 +0000138Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
Armando Montanez1e4b3702018-12-03 19:30:52 +0000139 yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
140
141 YamlOut << const_cast<ELFStub &>(Stub);
142 return Error::success();
143}