TBEHandler.cpp 5.1 KB

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