RuntimeDyldMachOI386.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. //===---- RuntimeDyldMachOI386.h ---- MachO/I386 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_RUNTIMEDYLDMACHOI386_H
  9. #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
  10. #include "../RuntimeDyldMachO.h"
  11. #define DEBUG_TYPE "dyld"
  12. namespace llvm {
  13. class RuntimeDyldMachOI386
  14. : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> {
  15. public:
  16. typedef uint32_t TargetPtrT;
  17. RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM,
  18. JITSymbolResolver &Resolver)
  19. : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
  20. unsigned getMaxStubSize() const override { return 0; }
  21. unsigned getStubAlignment() override { return 1; }
  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 (Obj.isRelocationScattered(RelInfo)) {
  33. if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
  34. RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
  35. return processSECTDIFFRelocation(SectionID, RelI, Obj,
  36. ObjSectionToID);
  37. else if (RelType == MachO::GENERIC_RELOC_VANILLA)
  38. return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID);
  39. return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation "
  40. "type: " + Twine(RelType)).str());
  41. }
  42. switch (RelType) {
  43. UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR);
  44. UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR);
  45. UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV);
  46. default:
  47. if (RelType > MachO::GENERIC_RELOC_TLV)
  48. return make_error<RuntimeDyldError>(("MachO I386 relocation type " +
  49. Twine(RelType) +
  50. " is out of range").str());
  51. break;
  52. }
  53. RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
  54. RE.Addend = memcpyAddend(RE);
  55. RelocationValueRef Value;
  56. if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
  57. Value = *ValueOrErr;
  58. else
  59. return ValueOrErr.takeError();
  60. // Addends for external, PC-rel relocations on i386 point back to the zero
  61. // offset. Calculate the final offset from the relocation target instead.
  62. // This allows us to use the same logic for both external and internal
  63. // relocations in resolveI386RelocationRef.
  64. // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
  65. // if (IsExtern && RE.IsPCRel) {
  66. // uint64_t RelocAddr = 0;
  67. // RelI->getAddress(RelocAddr);
  68. // Value.Addend += RelocAddr + 4;
  69. // }
  70. if (RE.IsPCRel)
  71. makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
  72. RE.Addend = Value.Offset;
  73. if (Value.SymbolName)
  74. addRelocationForSymbol(RE, Value.SymbolName);
  75. else
  76. addRelocationForSection(RE, Value.SectionID);
  77. return ++RelI;
  78. }
  79. void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
  80. LLVM_DEBUG(dumpRelocationToResolve(RE, Value));
  81. const SectionEntry &Section = Sections[RE.SectionID];
  82. uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
  83. if (RE.IsPCRel) {
  84. uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
  85. Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
  86. }
  87. switch (RE.RelType) {
  88. case MachO::GENERIC_RELOC_VANILLA:
  89. writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
  90. break;
  91. case MachO::GENERIC_RELOC_SECTDIFF:
  92. case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
  93. uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
  94. uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
  95. assert((Value == SectionABase || Value == SectionBBase) &&
  96. "Unexpected SECTDIFF relocation value.");
  97. Value = SectionABase - SectionBBase + RE.Addend;
  98. writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
  99. break;
  100. }
  101. default:
  102. llvm_unreachable("Invalid relocation type!");
  103. }
  104. }
  105. Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
  106. const SectionRef &Section) {
  107. StringRef Name;
  108. if (Expected<StringRef> NameOrErr = Section.getName())
  109. Name = *NameOrErr;
  110. else
  111. consumeError(NameOrErr.takeError());
  112. if (Name == "__jump_table")
  113. return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
  114. else if (Name == "__pointers")
  115. return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
  116. Section, SectionID);
  117. return Error::success();
  118. }
  119. private:
  120. Expected<relocation_iterator>
  121. processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
  122. const ObjectFile &BaseObjT,
  123. ObjSectionToIDMap &ObjSectionToID) {
  124. const MachOObjectFile &Obj =
  125. static_cast<const MachOObjectFile&>(BaseObjT);
  126. MachO::any_relocation_info RE =
  127. Obj.getRelocation(RelI->getRawDataRefImpl());
  128. SectionEntry &Section = Sections[SectionID];
  129. uint32_t RelocType = Obj.getAnyRelocationType(RE);
  130. bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
  131. unsigned Size = Obj.getAnyRelocationLength(RE);
  132. uint64_t Offset = RelI->getOffset();
  133. uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
  134. unsigned NumBytes = 1 << Size;
  135. uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
  136. ++RelI;
  137. MachO::any_relocation_info RE2 =
  138. Obj.getRelocation(RelI->getRawDataRefImpl());
  139. uint32_t AddrA = Obj.getScatteredRelocationValue(RE);
  140. section_iterator SAI = getSectionByAddress(Obj, AddrA);
  141. assert(SAI != Obj.section_end() && "Can't find section for address A");
  142. uint64_t SectionABase = SAI->getAddress();
  143. uint64_t SectionAOffset = AddrA - SectionABase;
  144. SectionRef SectionA = *SAI;
  145. bool IsCode = SectionA.isText();
  146. uint32_t SectionAID = ~0U;
  147. if (auto SectionAIDOrErr =
  148. findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID))
  149. SectionAID = *SectionAIDOrErr;
  150. else
  151. return SectionAIDOrErr.takeError();
  152. uint32_t AddrB = Obj.getScatteredRelocationValue(RE2);
  153. section_iterator SBI = getSectionByAddress(Obj, AddrB);
  154. assert(SBI != Obj.section_end() && "Can't find section for address B");
  155. uint64_t SectionBBase = SBI->getAddress();
  156. uint64_t SectionBOffset = AddrB - SectionBBase;
  157. SectionRef SectionB = *SBI;
  158. uint32_t SectionBID = ~0U;
  159. if (auto SectionBIDOrErr =
  160. findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID))
  161. SectionBID = *SectionBIDOrErr;
  162. else
  163. return SectionBIDOrErr.takeError();
  164. // Compute the addend 'C' from the original expression 'A - B + C'.
  165. Addend -= AddrA - AddrB;
  166. LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA
  167. << ", AddrB: " << AddrB << ", Addend: " << Addend
  168. << ", SectionA ID: " << SectionAID << ", SectionAOffset: "
  169. << SectionAOffset << ", SectionB ID: " << SectionBID
  170. << ", SectionBOffset: " << SectionBOffset << "\n");
  171. RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
  172. SectionAOffset, SectionBID, SectionBOffset,
  173. IsPCRel, Size);
  174. addRelocationForSection(R, SectionAID);
  175. return ++RelI;
  176. }
  177. // Populate stubs in __jump_table section.
  178. Error populateJumpTable(const MachOObjectFile &Obj,
  179. const SectionRef &JTSection,
  180. unsigned JTSectionID) {
  181. MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
  182. MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
  183. uint32_t JTSectionSize = Sec32.size;
  184. unsigned FirstIndirectSymbol = Sec32.reserved1;
  185. unsigned JTEntrySize = Sec32.reserved2;
  186. unsigned NumJTEntries = JTSectionSize / JTEntrySize;
  187. uint8_t *JTSectionAddr = getSectionAddress(JTSectionID);
  188. unsigned JTEntryOffset = 0;
  189. if (JTSectionSize % JTEntrySize != 0)
  190. return make_error<RuntimeDyldError>("Jump-table section does not contain "
  191. "a whole number of stubs?");
  192. for (unsigned i = 0; i < NumJTEntries; ++i) {
  193. unsigned SymbolIndex =
  194. Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
  195. symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
  196. Expected<StringRef> IndirectSymbolName = SI->getName();
  197. if (!IndirectSymbolName)
  198. return IndirectSymbolName.takeError();
  199. uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset;
  200. createStubFunction(JTEntryAddr);
  201. RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
  202. MachO::GENERIC_RELOC_VANILLA, 0, true, 2);
  203. addRelocationForSymbol(RE, *IndirectSymbolName);
  204. JTEntryOffset += JTEntrySize;
  205. }
  206. return Error::success();
  207. }
  208. };
  209. }
  210. #undef DEBUG_TYPE
  211. #endif