IFSHandler.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //===- IFSHandler.cpp -----------------------------------------------------===//
  2. //
  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
  6. //
  7. //===-----------------------------------------------------------------------===/
  8. #include "llvm/InterfaceStub/IFSHandler.h"
  9. #include "llvm/ADT/StringRef.h"
  10. #include "llvm/ADT/StringSwitch.h"
  11. #include "llvm/ADT/Triple.h"
  12. #include "llvm/BinaryFormat/ELF.h"
  13. #include "llvm/InterfaceStub/IFSStub.h"
  14. #include "llvm/Support/Error.h"
  15. #include "llvm/Support/LineIterator.h"
  16. #include "llvm/Support/YAMLTraits.h"
  17. using namespace llvm;
  18. using namespace llvm::ifs;
  19. LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
  20. namespace llvm {
  21. namespace yaml {
  22. /// YAML traits for ELFSymbolType.
  23. template <> struct ScalarEnumerationTraits<IFSSymbolType> {
  24. static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
  25. IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
  26. IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
  27. IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
  28. IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS);
  29. IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
  30. // Treat other symbol types as noise, and map to Unknown.
  31. if (!IO.outputting() && IO.matchEnumFallback())
  32. SymbolType = IFSSymbolType::Unknown;
  33. }
  34. };
  35. template <> struct ScalarTraits<IFSEndiannessType> {
  36. static void output(const IFSEndiannessType &Value, void *,
  37. llvm::raw_ostream &Out) {
  38. switch (Value) {
  39. case IFSEndiannessType::Big:
  40. Out << "big";
  41. break;
  42. case IFSEndiannessType::Little:
  43. Out << "little";
  44. break;
  45. default:
  46. llvm_unreachable("Unsupported endianness");
  47. }
  48. }
  49. static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) {
  50. Value = StringSwitch<IFSEndiannessType>(Scalar)
  51. .Case("big", IFSEndiannessType::Big)
  52. .Case("little", IFSEndiannessType::Little)
  53. .Default(IFSEndiannessType::Unknown);
  54. if (Value == IFSEndiannessType::Unknown) {
  55. return "Unsupported endianness";
  56. }
  57. return StringRef();
  58. }
  59. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  60. };
  61. template <> struct ScalarTraits<IFSBitWidthType> {
  62. static void output(const IFSBitWidthType &Value, void *,
  63. llvm::raw_ostream &Out) {
  64. switch (Value) {
  65. case IFSBitWidthType::IFS32:
  66. Out << "32";
  67. break;
  68. case IFSBitWidthType::IFS64:
  69. Out << "64";
  70. break;
  71. default:
  72. llvm_unreachable("Unsupported bit width");
  73. }
  74. }
  75. static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) {
  76. Value = StringSwitch<IFSBitWidthType>(Scalar)
  77. .Case("32", IFSBitWidthType::IFS32)
  78. .Case("64", IFSBitWidthType::IFS64)
  79. .Default(IFSBitWidthType::Unknown);
  80. if (Value == IFSBitWidthType::Unknown) {
  81. return "Unsupported bit width";
  82. }
  83. return StringRef();
  84. }
  85. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  86. };
  87. template <> struct MappingTraits<IFSTarget> {
  88. static void mapping(IO &IO, IFSTarget &Target) {
  89. IO.mapOptional("ObjectFormat", Target.ObjectFormat);
  90. IO.mapOptional("Arch", Target.ArchString);
  91. IO.mapOptional("Endianness", Target.Endianness);
  92. IO.mapOptional("BitWidth", Target.BitWidth);
  93. }
  94. // Compacts symbol information into a single line.
  95. static const bool flow = true; // NOLINT(readability-identifier-naming)
  96. };
  97. /// YAML traits for ELFSymbol.
  98. template <> struct MappingTraits<IFSSymbol> {
  99. static void mapping(IO &IO, IFSSymbol &Symbol) {
  100. IO.mapRequired("Name", Symbol.Name);
  101. IO.mapRequired("Type", Symbol.Type);
  102. // The need for symbol size depends on the symbol type.
  103. if (Symbol.Type == IFSSymbolType::NoType) {
  104. IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
  105. } else if (Symbol.Type == IFSSymbolType::Func) {
  106. Symbol.Size = 0;
  107. } else {
  108. IO.mapRequired("Size", Symbol.Size);
  109. }
  110. IO.mapOptional("Undefined", Symbol.Undefined, false);
  111. IO.mapOptional("Weak", Symbol.Weak, false);
  112. IO.mapOptional("Warning", Symbol.Warning);
  113. }
  114. // Compacts symbol information into a single line.
  115. static const bool flow = true; // NOLINT(readability-identifier-naming)
  116. };
  117. /// YAML traits for ELFStub objects.
  118. template <> struct MappingTraits<IFSStub> {
  119. static void mapping(IO &IO, IFSStub &Stub) {
  120. if (!IO.mapTag("!ifs-v1", true))
  121. IO.setError("Not a .tbe YAML file.");
  122. IO.mapRequired("IfsVersion", Stub.IfsVersion);
  123. IO.mapOptional("SoName", Stub.SoName);
  124. IO.mapOptional("Target", Stub.Target);
  125. IO.mapOptional("NeededLibs", Stub.NeededLibs);
  126. IO.mapRequired("Symbols", Stub.Symbols);
  127. }
  128. };
  129. /// YAML traits for ELFStubTriple objects.
  130. template <> struct MappingTraits<IFSStubTriple> {
  131. static void mapping(IO &IO, IFSStubTriple &Stub) {
  132. if (!IO.mapTag("!ifs-v1", true))
  133. IO.setError("Not a .tbe YAML file.");
  134. IO.mapRequired("IfsVersion", Stub.IfsVersion);
  135. IO.mapOptional("SoName", Stub.SoName);
  136. IO.mapOptional("Target", Stub.Target.Triple);
  137. IO.mapOptional("NeededLibs", Stub.NeededLibs);
  138. IO.mapRequired("Symbols", Stub.Symbols);
  139. }
  140. };
  141. } // end namespace yaml
  142. } // end namespace llvm
  143. /// Attempt to determine if a Text stub uses target triple.
  144. bool usesTriple(StringRef Buf) {
  145. for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) {
  146. StringRef Line = (*I).trim();
  147. if (Line.startswith("Target:")) {
  148. if (Line == "Target:" || Line.contains("{")) {
  149. return false;
  150. }
  151. }
  152. }
  153. return true;
  154. }
  155. Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) {
  156. yaml::Input YamlIn(Buf);
  157. std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
  158. if (usesTriple(Buf)) {
  159. YamlIn >> *Stub;
  160. } else {
  161. YamlIn >> *static_cast<IFSStub *>(Stub.get());
  162. }
  163. if (std::error_code Err = YamlIn.error()) {
  164. return createStringError(Err, "YAML failed reading as IFS");
  165. }
  166. if (Stub->IfsVersion > IFSVersionCurrent)
  167. return make_error<StringError>(
  168. "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
  169. std::make_error_code(std::errc::invalid_argument));
  170. if (Stub->Target.ArchString) {
  171. Stub->Target.Arch =
  172. ELF::convertArchNameToEMachine(Stub->Target.ArchString.getValue());
  173. }
  174. return std::move(Stub);
  175. }
  176. Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) {
  177. yaml::Output YamlOut(OS, nullptr, /*WrapColumn =*/0);
  178. std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
  179. if (Stub.Target.Arch) {
  180. CopyStub->Target.ArchString = std::string(
  181. ELF::convertEMachineToArchName(Stub.Target.Arch.getValue()));
  182. }
  183. IFSTarget Target = Stub.Target;
  184. if (CopyStub->Target.Triple ||
  185. (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness &&
  186. !CopyStub->Target.BitWidth))
  187. YamlOut << *CopyStub;
  188. else
  189. YamlOut << *static_cast<IFSStub *>(CopyStub.get());
  190. return Error::success();
  191. }
  192. Error ifs::overrideIFSTarget(IFSStub &Stub, Optional<IFSArch> OverrideArch,
  193. Optional<IFSEndiannessType> OverrideEndianness,
  194. Optional<IFSBitWidthType> OverrideBitWidth,
  195. Optional<std::string> OverrideTriple) {
  196. std::error_code OverrideEC(1, std::generic_category());
  197. if (OverrideArch) {
  198. if (Stub.Target.Arch &&
  199. Stub.Target.Arch.getValue() != OverrideArch.getValue()) {
  200. return make_error<StringError>(
  201. "Supplied Arch conflicts with the text stub", OverrideEC);
  202. }
  203. Stub.Target.Arch = OverrideArch.getValue();
  204. }
  205. if (OverrideEndianness) {
  206. if (Stub.Target.Endianness &&
  207. Stub.Target.Endianness.getValue() != OverrideEndianness.getValue()) {
  208. return make_error<StringError>(
  209. "Supplied Endianness conflicts with the text stub", OverrideEC);
  210. }
  211. Stub.Target.Endianness = OverrideEndianness.getValue();
  212. }
  213. if (OverrideBitWidth) {
  214. if (Stub.Target.BitWidth &&
  215. Stub.Target.BitWidth.getValue() != OverrideBitWidth.getValue()) {
  216. return make_error<StringError>(
  217. "Supplied BitWidth conflicts with the text stub", OverrideEC);
  218. }
  219. Stub.Target.BitWidth = OverrideBitWidth.getValue();
  220. }
  221. if (OverrideTriple) {
  222. if (Stub.Target.Triple &&
  223. Stub.Target.Triple.getValue() != OverrideTriple.getValue()) {
  224. return make_error<StringError>(
  225. "Supplied Triple conflicts with the text stub", OverrideEC);
  226. }
  227. Stub.Target.Triple = OverrideTriple.getValue();
  228. }
  229. return Error::success();
  230. }
  231. Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) {
  232. std::error_code ValidationEC(1, std::generic_category());
  233. if (Stub.Target.Triple) {
  234. if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness ||
  235. Stub.Target.ObjectFormat) {
  236. return make_error<StringError>(
  237. "Target triple cannot be used simultaneously with ELF target format",
  238. ValidationEC);
  239. }
  240. if (ParseTriple) {
  241. IFSTarget TargetFromTriple = parseTriple(Stub.Target.Triple.getValue());
  242. Stub.Target.Arch = TargetFromTriple.Arch;
  243. Stub.Target.BitWidth = TargetFromTriple.BitWidth;
  244. Stub.Target.Endianness = TargetFromTriple.Endianness;
  245. }
  246. return Error::success();
  247. }
  248. if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) {
  249. // TODO: unify the error message.
  250. if (!Stub.Target.Arch) {
  251. return make_error<StringError>("Arch is not defined in the text stub",
  252. ValidationEC);
  253. }
  254. if (!Stub.Target.BitWidth) {
  255. return make_error<StringError>("BitWidth is not defined in the text stub",
  256. ValidationEC);
  257. }
  258. if (!Stub.Target.Endianness) {
  259. return make_error<StringError>(
  260. "Endianness is not defined in the text stub", ValidationEC);
  261. }
  262. }
  263. return Error::success();
  264. }
  265. IFSTarget ifs::parseTriple(StringRef TripleStr) {
  266. Triple IFSTriple(TripleStr);
  267. IFSTarget RetTarget;
  268. // TODO: Implement a Triple Arch enum to e_machine map.
  269. switch (IFSTriple.getArch()) {
  270. case Triple::ArchType::aarch64:
  271. RetTarget.Arch = (IFSArch)ELF::EM_AARCH64;
  272. break;
  273. case Triple::ArchType::x86_64:
  274. RetTarget.Arch = (IFSArch)ELF::EM_X86_64;
  275. break;
  276. default:
  277. RetTarget.Arch = (IFSArch)ELF::EM_NONE;
  278. }
  279. RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
  280. : IFSEndiannessType::Big;
  281. RetTarget.BitWidth =
  282. IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
  283. return RetTarget;
  284. }
  285. void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
  286. bool StripEndianness, bool StripBitWidth) {
  287. if (StripTriple || StripArch) {
  288. Stub.Target.Arch.reset();
  289. Stub.Target.ArchString.reset();
  290. }
  291. if (StripTriple || StripEndianness) {
  292. Stub.Target.Endianness.reset();
  293. }
  294. if (StripTriple || StripBitWidth) {
  295. Stub.Target.BitWidth.reset();
  296. }
  297. if (StripTriple) {
  298. Stub.Target.Triple.reset();
  299. }
  300. if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) {
  301. Stub.Target.ObjectFormat.reset();
  302. }
  303. }
  304. void ifs::stripIFSUndefinedSymbols(IFSStub &Stub) {
  305. for (auto Iter = Stub.Symbols.begin(); Iter != Stub.Symbols.end();) {
  306. if (Iter->Undefined) {
  307. Iter = Stub.Symbols.erase(Iter);
  308. } else {
  309. Iter++;
  310. }
  311. }
  312. }