ELF_loongarch.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //===--- ELF_loongarch.cpp - JIT linker implementation for ELF/loongarch --===//
  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. //
  9. // ELF/loongarch jit-link implementation.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h"
  13. #include "llvm/BinaryFormat/ELF.h"
  14. #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
  15. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  16. #include "llvm/ExecutionEngine/JITLink/loongarch.h"
  17. #include "llvm/Object/ELF.h"
  18. #include "llvm/Object/ELFObjectFile.h"
  19. #include "EHFrameSupportImpl.h"
  20. #include "ELFLinkGraphBuilder.h"
  21. #include "JITLinkGeneric.h"
  22. #define DEBUG_TYPE "jitlink"
  23. using namespace llvm;
  24. using namespace llvm::jitlink;
  25. using namespace llvm::jitlink::loongarch;
  26. namespace {
  27. class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
  28. friend class JITLinker<ELFJITLinker_loongarch>;
  29. public:
  30. ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx,
  31. std::unique_ptr<LinkGraph> G,
  32. PassConfiguration PassConfig)
  33. : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
  34. private:
  35. Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
  36. return loongarch::applyFixup(G, B, E);
  37. }
  38. };
  39. template <typename ELFT>
  40. class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
  41. private:
  42. static Expected<loongarch::EdgeKind_loongarch>
  43. getRelocationKind(const uint32_t Type) {
  44. using namespace loongarch;
  45. switch (Type) {
  46. case ELF::R_LARCH_64:
  47. return Pointer64;
  48. case ELF::R_LARCH_32:
  49. return Pointer32;
  50. case ELF::R_LARCH_32_PCREL:
  51. return Delta32;
  52. case ELF::R_LARCH_B26:
  53. return Branch26PCRel;
  54. case ELF::R_LARCH_PCALA_HI20:
  55. return Page20;
  56. case ELF::R_LARCH_PCALA_LO12:
  57. return PageOffset12;
  58. case ELF::R_LARCH_GOT_PC_HI20:
  59. return RequestGOTAndTransformToPage20;
  60. case ELF::R_LARCH_GOT_PC_LO12:
  61. return RequestGOTAndTransformToPageOffset12;
  62. }
  63. return make_error<JITLinkError>(
  64. "Unsupported loongarch relocation:" + formatv("{0:d}: ", Type) +
  65. object::getELFRelocationTypeName(ELF::EM_LOONGARCH, Type));
  66. }
  67. Error addRelocations() override {
  68. LLVM_DEBUG(dbgs() << "Processing relocations:\n");
  69. using Base = ELFLinkGraphBuilder<ELFT>;
  70. using Self = ELFLinkGraphBuilder_loongarch<ELFT>;
  71. for (const auto &RelSect : Base::Sections)
  72. if (Error Err = Base::forEachRelaRelocation(RelSect, this,
  73. &Self::addSingleRelocation))
  74. return Err;
  75. return Error::success();
  76. }
  77. Error addSingleRelocation(const typename ELFT::Rela &Rel,
  78. const typename ELFT::Shdr &FixupSect,
  79. Block &BlockToFix) {
  80. using Base = ELFLinkGraphBuilder<ELFT>;
  81. uint32_t SymbolIndex = Rel.getSymbol(false);
  82. auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
  83. if (!ObjSymbol)
  84. return ObjSymbol.takeError();
  85. Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
  86. if (!GraphSymbol)
  87. return make_error<StringError>(
  88. formatv("Could not find symbol at given index, did you add it to "
  89. "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
  90. SymbolIndex, (*ObjSymbol)->st_shndx,
  91. Base::GraphSymbols.size()),
  92. inconvertibleErrorCode());
  93. uint32_t Type = Rel.getType(false);
  94. Expected<loongarch::EdgeKind_loongarch> Kind = getRelocationKind(Type);
  95. if (!Kind)
  96. return Kind.takeError();
  97. int64_t Addend = Rel.r_addend;
  98. auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
  99. Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
  100. Edge GE(*Kind, Offset, *GraphSymbol, Addend);
  101. LLVM_DEBUG({
  102. dbgs() << " ";
  103. printEdge(dbgs(), BlockToFix, GE, loongarch::getEdgeKindName(*Kind));
  104. dbgs() << "\n";
  105. });
  106. BlockToFix.addEdge(std::move(GE));
  107. return Error::success();
  108. }
  109. public:
  110. ELFLinkGraphBuilder_loongarch(StringRef FileName,
  111. const object::ELFFile<ELFT> &Obj,
  112. const Triple T)
  113. : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
  114. loongarch::getEdgeKindName) {}
  115. };
  116. Error buildTables_ELF_loongarch(LinkGraph &G) {
  117. LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
  118. GOTTableManager GOT;
  119. PLTTableManager PLT(GOT);
  120. visitExistingEdges(G, GOT, PLT);
  121. return Error::success();
  122. }
  123. } // namespace
  124. namespace llvm {
  125. namespace jitlink {
  126. Expected<std::unique_ptr<LinkGraph>>
  127. createLinkGraphFromELFObject_loongarch(MemoryBufferRef ObjectBuffer) {
  128. LLVM_DEBUG({
  129. dbgs() << "Building jitlink graph for new input "
  130. << ObjectBuffer.getBufferIdentifier() << "...\n";
  131. });
  132. auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
  133. if (!ELFObj)
  134. return ELFObj.takeError();
  135. if ((*ELFObj)->getArch() == Triple::loongarch64) {
  136. auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
  137. return ELFLinkGraphBuilder_loongarch<object::ELF64LE>(
  138. (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
  139. (*ELFObj)->makeTriple())
  140. .buildGraph();
  141. }
  142. assert((*ELFObj)->getArch() == Triple::loongarch32 &&
  143. "Invalid triple for LoongArch ELF object file");
  144. auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
  145. return ELFLinkGraphBuilder_loongarch<object::ELF32LE>(
  146. (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
  147. (*ELFObj)->makeTriple())
  148. .buildGraph();
  149. }
  150. void link_ELF_loongarch(std::unique_ptr<LinkGraph> G,
  151. std::unique_ptr<JITLinkContext> Ctx) {
  152. PassConfiguration Config;
  153. const Triple &TT = G->getTargetTriple();
  154. if (Ctx->shouldAddDefaultTargetPasses(TT)) {
  155. // Add eh-frame passses.
  156. Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
  157. Config.PrePrunePasses.push_back(
  158. EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), Pointer32, Pointer64,
  159. Delta32, Delta64, NegDelta32));
  160. Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
  161. // Add a mark-live pass.
  162. if (auto MarkLive = Ctx->getMarkLivePass(TT))
  163. Config.PrePrunePasses.push_back(std::move(MarkLive));
  164. else
  165. Config.PrePrunePasses.push_back(markAllSymbolsLive);
  166. // Add an in-place GOT/PLTStubs build pass.
  167. Config.PostPrunePasses.push_back(buildTables_ELF_loongarch);
  168. }
  169. if (auto Err = Ctx->modifyPassConfig(*G, Config))
  170. return Ctx->notifyFailed(std::move(Err));
  171. ELFJITLinker_loongarch::link(std::move(Ctx), std::move(G), std::move(Config));
  172. }
  173. } // namespace jitlink
  174. } // namespace llvm