1 //===- TBEHandler.cpp -----------------------------------------------------===//
3 // 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
7 //===-----------------------------------------------------------------------===/
9 #include "llvm/TextAPI/ELF/TBEHandler.h"
10 #include "llvm/ADT/StringSwitch.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/YAMLTraits.h"
14 #include "llvm/TextAPI/ELF/ELFStub.h"
17 using namespace llvm::elfabi
;
19 LLVM_YAML_STRONG_TYPEDEF(ELFArch
, ELFArchMapper
)
24 /// YAML traits for ELFSymbolType.
25 template <> 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
;
38 /// YAML traits for ELFArch.
39 template <> struct ScalarTraits
<ELFArchMapper
> {
40 static void output(const ELFArchMapper
&Value
, void *,
41 llvm::raw_ostream
&Out
) {
42 // Map from integer to architecture string.
44 case (ELFArch
)ELF::EM_X86_64
:
47 case (ELFArch
)ELF::EM_AARCH64
:
50 case (ELFArch
)ELF::EM_NONE
:
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
);
64 // Returning empty StringRef indicates successful parse.
68 // Don't place quotation marks around architecture value.
69 static QuotingType
mustQuote(StringRef
) { return QuotingType::None
; }
72 /// YAML traits for TbeVersion.
73 template <> struct ScalarTraits
<VersionTuple
> {
74 static void output(const VersionTuple
&Value
, void *,
75 llvm::raw_ostream
&Out
) {
76 Out
<< Value
.getAsString();
79 static StringRef
input(StringRef Scalar
, void *, VersionTuple
&Value
) {
80 if (Value
.tryParse(Scalar
))
81 return StringRef("Can't parse version: invalid version format.");
83 if (Value
> TBEVersionCurrent
)
84 return StringRef("Unsupported TBE version.");
86 // Returning empty StringRef indicates successful parse.
90 // Don't place quotation marks around version value.
91 static QuotingType
mustQuote(StringRef
) { return QuotingType::None
; }
94 /// YAML traits for ELFSymbol.
95 template <> struct MappingTraits
<ELFSymbol
> {
96 static void mapping(IO
&IO
, ELFSymbol
&Symbol
) {
97 IO
.mapRequired("Type", Symbol
.Type
);
98 // The need for symbol size depends on the symbol type.
99 if (Symbol
.Type
== ELFSymbolType::NoType
) {
100 IO
.mapOptional("Size", Symbol
.Size
, (uint64_t)0);
101 } else if (Symbol
.Type
== ELFSymbolType::Func
) {
104 IO
.mapRequired("Size", Symbol
.Size
);
106 IO
.mapOptional("Undefined", Symbol
.Undefined
, false);
107 IO
.mapOptional("Weak", Symbol
.Weak
, false);
108 IO
.mapOptional("Warning", Symbol
.Warning
);
111 // Compacts symbol information into a single line.
112 static const bool flow
= true;
115 /// YAML traits for set of ELFSymbols.
116 template <> 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
);
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
));
129 /// YAML traits for ELFStub objects.
130 template <> struct MappingTraits
<ELFStub
> {
131 static void mapping(IO
&IO
, ELFStub
&Stub
) {
132 if (!IO
.mapTag("!tapi-tbe", true))
133 IO
.setError("Not a .tbe YAML file.");
134 IO
.mapRequired("TbeVersion", Stub
.TbeVersion
);
135 IO
.mapOptional("SoName", Stub
.SoName
);
136 IO
.mapRequired("Arch", (ELFArchMapper
&)Stub
.Arch
);
137 IO
.mapOptional("NeededLibs", Stub
.NeededLibs
);
138 IO
.mapRequired("Symbols", Stub
.Symbols
);
142 } // end namespace yaml
143 } // end namespace llvm
145 Expected
<std::unique_ptr
<ELFStub
>> elfabi::readTBEFromBuffer(StringRef Buf
) {
146 yaml::Input
YamlIn(Buf
);
147 std::unique_ptr
<ELFStub
> Stub(new ELFStub());
149 if (std::error_code Err
= YamlIn
.error())
150 return createStringError(Err
, "YAML failed reading as TBE");
152 return std::move(Stub
);
155 Error
elfabi::writeTBEToOutputStream(raw_ostream
&OS
, const ELFStub
&Stub
) {
156 yaml::Output
YamlOut(OS
, NULL
, /*WrapColumn =*/0);
158 YamlOut
<< const_cast<ELFStub
&>(Stub
);
159 return Error::success();