RuntimeDyldMachOX86_64.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. //===-- RuntimeDyldMachOX86_64.h ---- MachO/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. #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H
  9. #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H
  10. #include "../RuntimeDyldMachO.h"
  11. #define DEBUG_TYPE "dyld"
  12. namespace llvm {
  13. class RuntimeDyldMachOX86_64
  14. : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOX86_64> {
  15. public:
  16. typedef uint64_t TargetPtrT;
  17. RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM,
  18. JITSymbolResolver &Resolver)
  19. : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
  20. unsigned getMaxStubSize() const override { return 8; }
  21. Align getStubAlignment() override { return Align(8); }
  22. Expected<relocation_iterator>
  23. processRelocationRef(unsigned SectionID, relocation_iterator RelI,
  24. const ObjectFile &BaseObjT,
  25. ObjSectionToIDMap &ObjSectionToID,
  26. StubMap &Stubs) override {
  27. const MachOObjectFile &Obj =
  28. static_cast<const MachOObjectFile &>(BaseObjT);
  29. MachO::any_relocation_info RelInfo =
  30. Obj.getRelocation(RelI->getRawDataRefImpl());
  31. uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
  32. if (RelType == MachO::X86_64_RELOC_SUBTRACTOR)
  33. return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);
  34. assert(!Obj.isRelocationScattered(RelInfo) &&
  35. "Scattered relocations not supported on X86_64");
  36. RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
  37. RE.Addend = memcpyAddend(RE);
  38. RelocationValueRef Value;
  39. if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
  40. Value = *ValueOrErr;
  41. else
  42. return ValueOrErr.takeError();
  43. bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
  44. if (!IsExtern && RE.IsPCRel)
  45. makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
  46. switch (RelType) {
  47. UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV);
  48. default:
  49. if (RelType > MachO::X86_64_RELOC_TLV)
  50. return make_error<RuntimeDyldError>(("MachO X86_64 relocation type " +
  51. Twine(RelType) +
  52. " is out of range").str());
  53. break;
  54. }
  55. if (RE.RelType == MachO::X86_64_RELOC_GOT ||
  56. RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
  57. processGOTRelocation(RE, Value, Stubs);
  58. else {
  59. RE.Addend = Value.Offset;
  60. if (Value.SymbolName)
  61. addRelocationForSymbol(RE, Value.SymbolName);
  62. else
  63. addRelocationForSection(RE, Value.SectionID);
  64. }
  65. return ++RelI;
  66. }
  67. void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
  68. LLVM_DEBUG(dumpRelocationToResolve(RE, Value));
  69. const SectionEntry &Section = Sections[RE.SectionID];
  70. uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
  71. // If the relocation is PC-relative, the value to be encoded is the
  72. // pointer difference.
  73. if (RE.IsPCRel) {
  74. // FIXME: It seems this value needs to be adjusted by 4 for an effective
  75. // PC address. Is that expected? Only for branches, perhaps?
  76. uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
  77. Value -= FinalAddress + 4;
  78. }
  79. switch (RE.RelType) {
  80. default:
  81. llvm_unreachable("Invalid relocation type!");
  82. case MachO::X86_64_RELOC_SIGNED_1:
  83. case MachO::X86_64_RELOC_SIGNED_2:
  84. case MachO::X86_64_RELOC_SIGNED_4:
  85. case MachO::X86_64_RELOC_SIGNED:
  86. case MachO::X86_64_RELOC_UNSIGNED:
  87. case MachO::X86_64_RELOC_BRANCH:
  88. writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
  89. break;
  90. case MachO::X86_64_RELOC_SUBTRACTOR: {
  91. uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
  92. uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
  93. assert((Value == SectionABase || Value == SectionBBase) &&
  94. "Unexpected SUBTRACTOR relocation value.");
  95. Value = SectionABase - SectionBBase + RE.Addend;
  96. writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
  97. break;
  98. }
  99. }
  100. }
  101. Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
  102. const SectionRef &Section) {
  103. return Error::success();
  104. }
  105. private:
  106. void processGOTRelocation(const RelocationEntry &RE,
  107. RelocationValueRef &Value, StubMap &Stubs) {
  108. SectionEntry &Section = Sections[RE.SectionID];
  109. assert(RE.IsPCRel);
  110. assert(RE.Size == 2);
  111. Value.Offset -= RE.Addend;
  112. RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value);
  113. uint8_t *Addr;
  114. if (i != Stubs.end()) {
  115. Addr = Section.getAddressWithOffset(i->second);
  116. } else {
  117. Stubs[Value] = Section.getStubOffset();
  118. uint8_t *GOTEntry = Section.getAddressWithOffset(Section.getStubOffset());
  119. RelocationEntry GOTRE(RE.SectionID, Section.getStubOffset(),
  120. MachO::X86_64_RELOC_UNSIGNED, Value.Offset, false,
  121. 3);
  122. if (Value.SymbolName)
  123. addRelocationForSymbol(GOTRE, Value.SymbolName);
  124. else
  125. addRelocationForSection(GOTRE, Value.SectionID);
  126. Section.advanceStubOffset(8);
  127. Addr = GOTEntry;
  128. }
  129. RelocationEntry TargetRE(RE.SectionID, RE.Offset,
  130. MachO::X86_64_RELOC_UNSIGNED, RE.Addend, true, 2);
  131. resolveRelocation(TargetRE, (uint64_t)Addr);
  132. }
  133. Expected<relocation_iterator>
  134. processSubtractRelocation(unsigned SectionID, relocation_iterator RelI,
  135. const MachOObjectFile &BaseObj,
  136. ObjSectionToIDMap &ObjSectionToID) {
  137. const MachOObjectFile &Obj =
  138. static_cast<const MachOObjectFile&>(BaseObj);
  139. MachO::any_relocation_info RE =
  140. Obj.getRelocation(RelI->getRawDataRefImpl());
  141. unsigned Size = Obj.getAnyRelocationLength(RE);
  142. uint64_t Offset = RelI->getOffset();
  143. uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset);
  144. unsigned NumBytes = 1 << Size;
  145. int64_t Addend =
  146. SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);
  147. unsigned SectionBID = ~0U;
  148. uint64_t SectionBOffset = 0;
  149. MachO::any_relocation_info RelInfo =
  150. Obj.getRelocation(RelI->getRawDataRefImpl());
  151. bool AIsExternal = BaseObj.getPlainRelocationExternal(RelInfo);
  152. if (AIsExternal) {
  153. Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName();
  154. if (!SubtrahendNameOrErr)
  155. return SubtrahendNameOrErr.takeError();
  156. auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr);
  157. SectionBID = SubtrahendI->second.getSectionID();
  158. SectionBOffset = SubtrahendI->second.getOffset();
  159. } else {
  160. SectionRef SecB = Obj.getAnyRelocationSection(RelInfo);
  161. bool IsCode = SecB.isText();
  162. Expected<unsigned> SectionBIDOrErr =
  163. findOrEmitSection(Obj, SecB, IsCode, ObjSectionToID);
  164. if (!SectionBIDOrErr)
  165. return SectionBIDOrErr.takeError();
  166. SectionBID = *SectionBIDOrErr;
  167. Addend += SecB.getAddress();
  168. }
  169. ++RelI;
  170. unsigned SectionAID = ~0U;
  171. uint64_t SectionAOffset = 0;
  172. RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
  173. bool BIsExternal = BaseObj.getPlainRelocationExternal(RelInfo);
  174. if (BIsExternal) {
  175. Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName();
  176. if (!MinuendNameOrErr)
  177. return MinuendNameOrErr.takeError();
  178. auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr);
  179. SectionAID = MinuendI->second.getSectionID();
  180. SectionAOffset = MinuendI->second.getOffset();
  181. } else {
  182. SectionRef SecA = Obj.getAnyRelocationSection(RelInfo);
  183. bool IsCode = SecA.isText();
  184. Expected<unsigned> SectionAIDOrErr =
  185. findOrEmitSection(Obj, SecA, IsCode, ObjSectionToID);
  186. if (!SectionAIDOrErr)
  187. return SectionAIDOrErr.takeError();
  188. SectionAID = *SectionAIDOrErr;
  189. Addend -= SecA.getAddress();
  190. }
  191. RelocationEntry R(SectionID, Offset, MachO::X86_64_RELOC_SUBTRACTOR, (uint64_t)Addend,
  192. SectionAID, SectionAOffset, SectionBID, SectionBOffset,
  193. false, Size);
  194. addRelocationForSection(R, SectionAID);
  195. return ++RelI;
  196. }
  197. };
  198. }
  199. #undef DEBUG_TYPE
  200. #endif