RuntimeDyldMachO.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- 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. // Implementation of the MC-JIT runtime dynamic linker.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "RuntimeDyldMachO.h"
  13. #include "Targets/RuntimeDyldMachOAArch64.h"
  14. #include "Targets/RuntimeDyldMachOARM.h"
  15. #include "Targets/RuntimeDyldMachOI386.h"
  16. #include "Targets/RuntimeDyldMachOX86_64.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/ADT/StringRef.h"
  19. using namespace llvm;
  20. using namespace llvm::object;
  21. #define DEBUG_TYPE "dyld"
  22. namespace {
  23. class LoadedMachOObjectInfo final
  24. : public LoadedObjectInfoHelper<LoadedMachOObjectInfo,
  25. RuntimeDyld::LoadedObjectInfo> {
  26. public:
  27. LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld,
  28. ObjSectionToIDMap ObjSecToIDMap)
  29. : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
  30. OwningBinary<ObjectFile>
  31. getObjectForDebug(const ObjectFile &Obj) const override {
  32. return OwningBinary<ObjectFile>();
  33. }
  34. };
  35. }
  36. namespace llvm {
  37. int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
  38. unsigned NumBytes = 1 << RE.Size;
  39. uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset;
  40. return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));
  41. }
  42. Expected<relocation_iterator>
  43. RuntimeDyldMachO::processScatteredVANILLA(
  44. unsigned SectionID, relocation_iterator RelI,
  45. const ObjectFile &BaseObjT,
  46. RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,
  47. bool TargetIsLocalThumbFunc) {
  48. const MachOObjectFile &Obj =
  49. static_cast<const MachOObjectFile&>(BaseObjT);
  50. MachO::any_relocation_info RE =
  51. Obj.getRelocation(RelI->getRawDataRefImpl());
  52. SectionEntry &Section = Sections[SectionID];
  53. uint32_t RelocType = Obj.getAnyRelocationType(RE);
  54. bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
  55. unsigned Size = Obj.getAnyRelocationLength(RE);
  56. uint64_t Offset = RelI->getOffset();
  57. uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
  58. unsigned NumBytes = 1 << Size;
  59. int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
  60. unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
  61. section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
  62. assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
  63. uint64_t SectionBaseAddr = TargetSI->getAddress();
  64. SectionRef TargetSection = *TargetSI;
  65. bool IsCode = TargetSection.isText();
  66. uint32_t TargetSectionID = ~0U;
  67. if (auto TargetSectionIDOrErr =
  68. findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID))
  69. TargetSectionID = *TargetSectionIDOrErr;
  70. else
  71. return TargetSectionIDOrErr.takeError();
  72. Addend -= SectionBaseAddr;
  73. RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
  74. R.IsTargetThumbFunc = TargetIsLocalThumbFunc;
  75. addRelocationForSection(R, TargetSectionID);
  76. return ++RelI;
  77. }
  78. Expected<RelocationValueRef>
  79. RuntimeDyldMachO::getRelocationValueRef(
  80. const ObjectFile &BaseTObj, const relocation_iterator &RI,
  81. const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
  82. const MachOObjectFile &Obj =
  83. static_cast<const MachOObjectFile &>(BaseTObj);
  84. MachO::any_relocation_info RelInfo =
  85. Obj.getRelocation(RI->getRawDataRefImpl());
  86. RelocationValueRef Value;
  87. bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
  88. if (IsExternal) {
  89. symbol_iterator Symbol = RI->getSymbol();
  90. StringRef TargetName;
  91. if (auto TargetNameOrErr = Symbol->getName())
  92. TargetName = *TargetNameOrErr;
  93. else
  94. return TargetNameOrErr.takeError();
  95. RTDyldSymbolTable::const_iterator SI =
  96. GlobalSymbolTable.find(TargetName.data());
  97. if (SI != GlobalSymbolTable.end()) {
  98. const auto &SymInfo = SI->second;
  99. Value.SectionID = SymInfo.getSectionID();
  100. Value.Offset = SymInfo.getOffset() + RE.Addend;
  101. } else {
  102. Value.SymbolName = TargetName.data();
  103. Value.Offset = RE.Addend;
  104. }
  105. } else {
  106. SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
  107. bool IsCode = Sec.isText();
  108. if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode,
  109. ObjSectionToID))
  110. Value.SectionID = *SectionIDOrErr;
  111. else
  112. return SectionIDOrErr.takeError();
  113. uint64_t Addr = Sec.getAddress();
  114. Value.Offset = RE.Addend - Addr;
  115. }
  116. return Value;
  117. }
  118. void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
  119. const relocation_iterator &RI,
  120. unsigned OffsetToNextPC) {
  121. auto &O = *cast<MachOObjectFile>(RI->getObject());
  122. section_iterator SecI = O.getRelocationRelocatedSection(RI);
  123. Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();
  124. }
  125. void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
  126. uint64_t Value) const {
  127. const SectionEntry &Section = Sections[RE.SectionID];
  128. uint8_t *LocalAddress = Section.getAddress() + RE.Offset;
  129. uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset;
  130. dbgs() << "resolveRelocation Section: " << RE.SectionID
  131. << " LocalAddress: " << format("%p", LocalAddress)
  132. << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress)
  133. << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend
  134. << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType
  135. << " Size: " << (1 << RE.Size) << "\n";
  136. }
  137. section_iterator
  138. RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
  139. uint64_t Addr) {
  140. section_iterator SI = Obj.section_begin();
  141. section_iterator SE = Obj.section_end();
  142. for (; SI != SE; ++SI) {
  143. uint64_t SAddr = SI->getAddress();
  144. uint64_t SSize = SI->getSize();
  145. if ((Addr >= SAddr) && (Addr < SAddr + SSize))
  146. return SI;
  147. }
  148. return SE;
  149. }
  150. // Populate __pointers section.
  151. Error RuntimeDyldMachO::populateIndirectSymbolPointersSection(
  152. const MachOObjectFile &Obj,
  153. const SectionRef &PTSection,
  154. unsigned PTSectionID) {
  155. assert(!Obj.is64Bit() &&
  156. "Pointer table section not supported in 64-bit MachO.");
  157. MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
  158. MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
  159. uint32_t PTSectionSize = Sec32.size;
  160. unsigned FirstIndirectSymbol = Sec32.reserved1;
  161. const unsigned PTEntrySize = 4;
  162. unsigned NumPTEntries = PTSectionSize / PTEntrySize;
  163. unsigned PTEntryOffset = 0;
  164. assert((PTSectionSize % PTEntrySize) == 0 &&
  165. "Pointers section does not contain a whole number of stubs?");
  166. LLVM_DEBUG(dbgs() << "Populating pointer table section "
  167. << Sections[PTSectionID].getName() << ", Section ID "
  168. << PTSectionID << ", " << NumPTEntries << " entries, "
  169. << PTEntrySize << " bytes each:\n");
  170. for (unsigned i = 0; i < NumPTEntries; ++i) {
  171. unsigned SymbolIndex =
  172. Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
  173. symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
  174. StringRef IndirectSymbolName;
  175. if (auto IndirectSymbolNameOrErr = SI->getName())
  176. IndirectSymbolName = *IndirectSymbolNameOrErr;
  177. else
  178. return IndirectSymbolNameOrErr.takeError();
  179. LLVM_DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
  180. << ", PT offset: " << PTEntryOffset << "\n");
  181. RelocationEntry RE(PTSectionID, PTEntryOffset,
  182. MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
  183. addRelocationForSymbol(RE, IndirectSymbolName);
  184. PTEntryOffset += PTEntrySize;
  185. }
  186. return Error::success();
  187. }
  188. bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
  189. return Obj.isMachO();
  190. }
  191. template <typename Impl>
  192. Error
  193. RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
  194. ObjSectionToIDMap &SectionMap) {
  195. unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
  196. unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
  197. unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
  198. for (const auto &Section : Obj.sections()) {
  199. StringRef Name;
  200. if (Expected<StringRef> NameOrErr = Section.getName())
  201. Name = *NameOrErr;
  202. else
  203. consumeError(NameOrErr.takeError());
  204. // Force emission of the __text, __eh_frame, and __gcc_except_tab sections
  205. // if they're present. Otherwise call down to the impl to handle other
  206. // sections that have already been emitted.
  207. if (Name == "__text") {
  208. if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap))
  209. TextSID = *TextSIDOrErr;
  210. else
  211. return TextSIDOrErr.takeError();
  212. } else if (Name == "__eh_frame") {
  213. if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false,
  214. SectionMap))
  215. EHFrameSID = *EHFrameSIDOrErr;
  216. else
  217. return EHFrameSIDOrErr.takeError();
  218. } else if (Name == "__gcc_except_tab") {
  219. if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true,
  220. SectionMap))
  221. ExceptTabSID = *ExceptTabSIDOrErr;
  222. else
  223. return ExceptTabSIDOrErr.takeError();
  224. } else {
  225. auto I = SectionMap.find(Section);
  226. if (I != SectionMap.end())
  227. if (auto Err = impl().finalizeSection(Obj, I->second, Section))
  228. return Err;
  229. }
  230. }
  231. UnregisteredEHFrameSections.push_back(
  232. EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
  233. return Error::success();
  234. }
  235. template <typename Impl>
  236. unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,
  237. int64_t DeltaForText,
  238. int64_t DeltaForEH) {
  239. typedef typename Impl::TargetPtrT TargetPtrT;
  240. LLVM_DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
  241. << ", Delta for EH: " << DeltaForEH << "\n");
  242. uint32_t Length = readBytesUnaligned(P, 4);
  243. P += 4;
  244. uint8_t *Ret = P + Length;
  245. uint32_t Offset = readBytesUnaligned(P, 4);
  246. if (Offset == 0) // is a CIE
  247. return Ret;
  248. P += 4;
  249. TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));
  250. TargetPtrT NewLocation = FDELocation - DeltaForText;
  251. writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));
  252. P += sizeof(TargetPtrT);
  253. // Skip the FDE address range
  254. P += sizeof(TargetPtrT);
  255. uint8_t Augmentationsize = *P;
  256. P += 1;
  257. if (Augmentationsize != 0) {
  258. TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));
  259. TargetPtrT NewLSDA = LSDA - DeltaForEH;
  260. writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));
  261. }
  262. return Ret;
  263. }
  264. static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
  265. int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -
  266. static_cast<int64_t>(B->getObjAddress());
  267. int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();
  268. return ObjDistance - MemDistance;
  269. }
  270. template <typename Impl>
  271. void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
  272. for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
  273. EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
  274. if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
  275. SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
  276. continue;
  277. SectionEntry *Text = &Sections[SectionInfo.TextSID];
  278. SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
  279. SectionEntry *ExceptTab = nullptr;
  280. if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
  281. ExceptTab = &Sections[SectionInfo.ExceptTabSID];
  282. int64_t DeltaForText = computeDelta(Text, EHFrame);
  283. int64_t DeltaForEH = 0;
  284. if (ExceptTab)
  285. DeltaForEH = computeDelta(ExceptTab, EHFrame);
  286. uint8_t *P = EHFrame->getAddress();
  287. uint8_t *End = P + EHFrame->getSize();
  288. while (P != End) {
  289. P = processFDE(P, DeltaForText, DeltaForEH);
  290. }
  291. MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),
  292. EHFrame->getSize());
  293. }
  294. UnregisteredEHFrameSections.clear();
  295. }
  296. std::unique_ptr<RuntimeDyldMachO>
  297. RuntimeDyldMachO::create(Triple::ArchType Arch,
  298. RuntimeDyld::MemoryManager &MemMgr,
  299. JITSymbolResolver &Resolver) {
  300. switch (Arch) {
  301. default:
  302. llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
  303. break;
  304. case Triple::arm:
  305. return std::make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
  306. case Triple::aarch64:
  307. return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
  308. case Triple::aarch64_32:
  309. return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
  310. case Triple::x86:
  311. return std::make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
  312. case Triple::x86_64:
  313. return std::make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
  314. }
  315. }
  316. std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
  317. RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
  318. if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
  319. return std::make_unique<LoadedMachOObjectInfo>(*this,
  320. *ObjSectionToIDOrErr);
  321. else {
  322. HasError = true;
  323. raw_string_ostream ErrStream(ErrorStr);
  324. logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);
  325. return nullptr;
  326. }
  327. }
  328. } // end namespace llvm