RuntimeDyldCOFFX86_64.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. //===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===//
  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. // COFF x86_x64 support for MC-JIT runtime dynamic linker.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
  13. #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
  14. #include "../RuntimeDyldCOFF.h"
  15. #include "llvm/BinaryFormat/COFF.h"
  16. #include "llvm/Object/COFF.h"
  17. #define DEBUG_TYPE "dyld"
  18. namespace llvm {
  19. class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
  20. private:
  21. // When a module is loaded we save the SectionID of the unwind
  22. // sections in a table until we receive a request to register all
  23. // unregisteredEH frame sections with the memory manager.
  24. SmallVector<SID, 2> UnregisteredEHFrameSections;
  25. SmallVector<SID, 2> RegisteredEHFrameSections;
  26. uint64_t ImageBase;
  27. // Fake an __ImageBase pointer by returning the section with the lowest adress
  28. uint64_t getImageBase() {
  29. if (!ImageBase) {
  30. ImageBase = std::numeric_limits<uint64_t>::max();
  31. for (const SectionEntry &Section : Sections)
  32. // The Sections list may contain sections that weren't loaded for
  33. // whatever reason: they may be debug sections, and ProcessAllSections
  34. // is false, or they may be sections that contain 0 bytes. If the
  35. // section isn't loaded, the load address will be 0, and it should not
  36. // be included in the ImageBase calculation.
  37. if (Section.getLoadAddress() != 0)
  38. ImageBase = std::min(ImageBase, Section.getLoadAddress());
  39. }
  40. return ImageBase;
  41. }
  42. void write32BitOffset(uint8_t *Target, int64_t Addend, uint64_t Delta) {
  43. uint64_t Result = Addend + Delta;
  44. assert(Result <= UINT32_MAX && "Relocation overflow");
  45. writeBytesUnaligned(Result, Target, 4);
  46. }
  47. public:
  48. RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
  49. JITSymbolResolver &Resolver)
  50. : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_AMD64_ADDR64),
  51. ImageBase(0) {}
  52. Align getStubAlignment() override { return Align(1); }
  53. // 2-byte jmp instruction + 32-bit relative address + 64-bit absolute jump
  54. unsigned getMaxStubSize() const override { return 14; }
  55. // The target location for the relocation is described by RE.SectionID and
  56. // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
  57. // SectionEntry has three members describing its location.
  58. // SectionEntry::Address is the address at which the section has been loaded
  59. // into memory in the current (host) process. SectionEntry::LoadAddress is
  60. // the address that the section will have in the target process.
  61. // SectionEntry::ObjAddress is the address of the bits for this section in the
  62. // original emitted object image (also in the current address space).
  63. //
  64. // Relocations will be applied as if the section were loaded at
  65. // SectionEntry::LoadAddress, but they will be applied at an address based
  66. // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer
  67. // to Target memory contents if they are required for value calculations.
  68. //
  69. // The Value parameter here is the load address of the symbol for the
  70. // relocation to be applied. For relocations which refer to symbols in the
  71. // current object Value will be the LoadAddress of the section in which
  72. // the symbol resides (RE.Addend provides additional information about the
  73. // symbol location). For external symbols, Value will be the address of the
  74. // symbol in the target address space.
  75. void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
  76. const SectionEntry &Section = Sections[RE.SectionID];
  77. uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
  78. switch (RE.RelType) {
  79. case COFF::IMAGE_REL_AMD64_REL32:
  80. case COFF::IMAGE_REL_AMD64_REL32_1:
  81. case COFF::IMAGE_REL_AMD64_REL32_2:
  82. case COFF::IMAGE_REL_AMD64_REL32_3:
  83. case COFF::IMAGE_REL_AMD64_REL32_4:
  84. case COFF::IMAGE_REL_AMD64_REL32_5: {
  85. uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
  86. // Delta is the distance from the start of the reloc to the end of the
  87. // instruction with the reloc.
  88. uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32);
  89. Value -= FinalAddress + Delta;
  90. uint64_t Result = Value + RE.Addend;
  91. assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow");
  92. assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow");
  93. writeBytesUnaligned(Result, Target, 4);
  94. break;
  95. }
  96. case COFF::IMAGE_REL_AMD64_ADDR32NB: {
  97. // ADDR32NB requires an offset less than 2GB from 'ImageBase'.
  98. // The MemoryManager can make sure this is always true by forcing the
  99. // memory layout to be: CodeSection < ReadOnlySection < ReadWriteSection.
  100. const uint64_t ImageBase = getImageBase();
  101. if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX))
  102. report_fatal_error("IMAGE_REL_AMD64_ADDR32NB relocation requires an "
  103. "ordered section layout");
  104. else {
  105. write32BitOffset(Target, RE.Addend, Value - ImageBase);
  106. }
  107. break;
  108. }
  109. case COFF::IMAGE_REL_AMD64_ADDR64: {
  110. writeBytesUnaligned(Value + RE.Addend, Target, 8);
  111. break;
  112. }
  113. case COFF::IMAGE_REL_AMD64_SECREL: {
  114. assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && "Relocation overflow");
  115. assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && "Relocation underflow");
  116. writeBytesUnaligned(RE.Addend, Target, 4);
  117. break;
  118. }
  119. default:
  120. llvm_unreachable("Relocation type not implemented yet!");
  121. break;
  122. }
  123. }
  124. std::tuple<uint64_t, uint64_t, uint64_t>
  125. generateRelocationStub(unsigned SectionID, StringRef TargetName,
  126. uint64_t Offset, uint64_t RelType, uint64_t Addend,
  127. StubMap &Stubs) {
  128. uintptr_t StubOffset;
  129. SectionEntry &Section = Sections[SectionID];
  130. RelocationValueRef OriginalRelValueRef;
  131. OriginalRelValueRef.SectionID = SectionID;
  132. OriginalRelValueRef.Offset = Offset;
  133. OriginalRelValueRef.Addend = Addend;
  134. OriginalRelValueRef.SymbolName = TargetName.data();
  135. auto Stub = Stubs.find(OriginalRelValueRef);
  136. if (Stub == Stubs.end()) {
  137. LLVM_DEBUG(dbgs() << " Create a new stub function for "
  138. << TargetName.data() << "\n");
  139. StubOffset = Section.getStubOffset();
  140. Stubs[OriginalRelValueRef] = StubOffset;
  141. createStubFunction(Section.getAddressWithOffset(StubOffset));
  142. Section.advanceStubOffset(getMaxStubSize());
  143. } else {
  144. LLVM_DEBUG(dbgs() << " Stub function found for " << TargetName.data()
  145. << "\n");
  146. StubOffset = Stub->second;
  147. }
  148. // FIXME: If RelType == COFF::IMAGE_REL_AMD64_ADDR32NB we should be able
  149. // to ignore the __ImageBase requirement and just forward to the stub
  150. // directly as an offset of this section:
  151. // write32BitOffset(Section.getAddressWithOffset(Offset), 0, StubOffset);
  152. // .xdata exception handler's aren't having this though.
  153. // Resolve original relocation to stub function.
  154. const RelocationEntry RE(SectionID, Offset, RelType, Addend);
  155. resolveRelocation(RE, Section.getLoadAddressWithOffset(StubOffset));
  156. // adjust relocation info so resolution writes to the stub function
  157. Addend = 0;
  158. Offset = StubOffset + 6;
  159. RelType = COFF::IMAGE_REL_AMD64_ADDR64;
  160. return std::make_tuple(Offset, RelType, Addend);
  161. }
  162. Expected<object::relocation_iterator>
  163. processRelocationRef(unsigned SectionID,
  164. object::relocation_iterator RelI,
  165. const object::ObjectFile &Obj,
  166. ObjSectionToIDMap &ObjSectionToID,
  167. StubMap &Stubs) override {
  168. // If possible, find the symbol referred to in the relocation,
  169. // and the section that contains it.
  170. object::symbol_iterator Symbol = RelI->getSymbol();
  171. if (Symbol == Obj.symbol_end())
  172. report_fatal_error("Unknown symbol in relocation");
  173. auto SectionOrError = Symbol->getSection();
  174. if (!SectionOrError)
  175. return SectionOrError.takeError();
  176. object::section_iterator SecI = *SectionOrError;
  177. // If there is no section, this must be an external reference.
  178. bool IsExtern = SecI == Obj.section_end();
  179. // Determine the Addend used to adjust the relocation value.
  180. uint64_t RelType = RelI->getType();
  181. uint64_t Offset = RelI->getOffset();
  182. uint64_t Addend = 0;
  183. SectionEntry &Section = Sections[SectionID];
  184. uintptr_t ObjTarget = Section.getObjAddress() + Offset;
  185. Expected<StringRef> TargetNameOrErr = Symbol->getName();
  186. if (!TargetNameOrErr)
  187. return TargetNameOrErr.takeError();
  188. StringRef TargetName = *TargetNameOrErr;
  189. unsigned TargetSectionID = 0;
  190. uint64_t TargetOffset = 0;
  191. if (TargetName.startswith(getImportSymbolPrefix())) {
  192. assert(IsExtern && "DLLImport not marked extern?");
  193. TargetSectionID = SectionID;
  194. TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName);
  195. TargetName = StringRef();
  196. IsExtern = false;
  197. } else if (!IsExtern) {
  198. if (auto TargetSectionIDOrErr =
  199. findOrEmitSection(Obj, *SecI, SecI->isText(), ObjSectionToID))
  200. TargetSectionID = *TargetSectionIDOrErr;
  201. else
  202. return TargetSectionIDOrErr.takeError();
  203. TargetOffset = getSymbolOffset(*Symbol);
  204. }
  205. switch (RelType) {
  206. case COFF::IMAGE_REL_AMD64_REL32:
  207. case COFF::IMAGE_REL_AMD64_REL32_1:
  208. case COFF::IMAGE_REL_AMD64_REL32_2:
  209. case COFF::IMAGE_REL_AMD64_REL32_3:
  210. case COFF::IMAGE_REL_AMD64_REL32_4:
  211. case COFF::IMAGE_REL_AMD64_REL32_5:
  212. case COFF::IMAGE_REL_AMD64_ADDR32NB: {
  213. uint8_t *Displacement = (uint8_t *)ObjTarget;
  214. Addend = readBytesUnaligned(Displacement, 4);
  215. if (IsExtern)
  216. std::tie(Offset, RelType, Addend) = generateRelocationStub(
  217. SectionID, TargetName, Offset, RelType, Addend, Stubs);
  218. break;
  219. }
  220. case COFF::IMAGE_REL_AMD64_ADDR64: {
  221. uint8_t *Displacement = (uint8_t *)ObjTarget;
  222. Addend = readBytesUnaligned(Displacement, 8);
  223. break;
  224. }
  225. default:
  226. break;
  227. }
  228. LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
  229. << " RelType: " << RelType << " TargetName: "
  230. << TargetName << " Addend " << Addend << "\n");
  231. if (IsExtern) {
  232. RelocationEntry RE(SectionID, Offset, RelType, Addend);
  233. addRelocationForSymbol(RE, TargetName);
  234. } else {
  235. RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
  236. addRelocationForSection(RE, TargetSectionID);
  237. }
  238. return ++RelI;
  239. }
  240. void registerEHFrames() override {
  241. for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
  242. uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
  243. uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
  244. size_t EHFrameSize = Sections[EHFrameSID].getSize();
  245. MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
  246. RegisteredEHFrameSections.push_back(EHFrameSID);
  247. }
  248. UnregisteredEHFrameSections.clear();
  249. }
  250. Error finalizeLoad(const object::ObjectFile &Obj,
  251. ObjSectionToIDMap &SectionMap) override {
  252. // Look for and record the EH frame section IDs.
  253. for (const auto &SectionPair : SectionMap) {
  254. const object::SectionRef &Section = SectionPair.first;
  255. Expected<StringRef> NameOrErr = Section.getName();
  256. if (!NameOrErr)
  257. return NameOrErr.takeError();
  258. // Note unwind info is stored in .pdata but often points to .xdata
  259. // with an IMAGE_REL_AMD64_ADDR32NB relocation. Using a memory manager
  260. // that keeps sections ordered in relation to __ImageBase is necessary.
  261. if ((*NameOrErr) == ".pdata")
  262. UnregisteredEHFrameSections.push_back(SectionPair.second);
  263. }
  264. return Error::success();
  265. }
  266. };
  267. } // end namespace llvm
  268. #undef DEBUG_TYPE
  269. #endif