MachOPlatform.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. //===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===//
  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. #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
  9. #include "llvm/BinaryFormat/MachO.h"
  10. #include "llvm/ExecutionEngine/JITLink/x86_64.h"
  11. #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
  12. #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
  13. #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
  14. #include "llvm/Support/BinaryByteStream.h"
  15. #include "llvm/Support/Debug.h"
  16. #define DEBUG_TYPE "orc"
  17. using namespace llvm;
  18. using namespace llvm::orc;
  19. using namespace llvm::orc::shared;
  20. namespace {
  21. class MachOHeaderMaterializationUnit : public MaterializationUnit {
  22. public:
  23. MachOHeaderMaterializationUnit(MachOPlatform &MOP,
  24. const SymbolStringPtr &HeaderStartSymbol)
  25. : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
  26. MOP(MOP) {}
  27. StringRef getName() const override { return "MachOHeaderMU"; }
  28. void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
  29. unsigned PointerSize;
  30. support::endianness Endianness;
  31. const auto &TT =
  32. MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
  33. switch (TT.getArch()) {
  34. case Triple::aarch64:
  35. case Triple::x86_64:
  36. PointerSize = 8;
  37. Endianness = support::endianness::little;
  38. break;
  39. default:
  40. llvm_unreachable("Unrecognized architecture");
  41. }
  42. auto G = std::make_unique<jitlink::LinkGraph>(
  43. "<MachOHeaderMU>", TT, PointerSize, Endianness,
  44. jitlink::getGenericEdgeKindName);
  45. auto &HeaderSection = G->createSection("__header", jitlink::MemProt::Read);
  46. auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
  47. // Init symbol is header-start symbol.
  48. G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(),
  49. HeaderBlock.getSize(), jitlink::Linkage::Strong,
  50. jitlink::Scope::Default, false, true);
  51. for (auto &HS : AdditionalHeaderSymbols)
  52. G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name,
  53. HeaderBlock.getSize(), jitlink::Linkage::Strong,
  54. jitlink::Scope::Default, false, true);
  55. MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  56. }
  57. void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
  58. private:
  59. struct HeaderSymbol {
  60. const char *Name;
  61. uint64_t Offset;
  62. };
  63. static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
  64. {"___mh_executable_header", 0}};
  65. static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
  66. jitlink::Section &HeaderSection) {
  67. MachO::mach_header_64 Hdr;
  68. Hdr.magic = MachO::MH_MAGIC_64;
  69. switch (G.getTargetTriple().getArch()) {
  70. case Triple::aarch64:
  71. Hdr.cputype = MachO::CPU_TYPE_ARM64;
  72. Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
  73. break;
  74. case Triple::x86_64:
  75. Hdr.cputype = MachO::CPU_TYPE_X86_64;
  76. Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
  77. break;
  78. default:
  79. llvm_unreachable("Unrecognized architecture");
  80. }
  81. Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
  82. Hdr.ncmds = 0;
  83. Hdr.sizeofcmds = 0;
  84. Hdr.flags = 0;
  85. Hdr.reserved = 0;
  86. if (G.getEndianness() != support::endian::system_endianness())
  87. MachO::swapStruct(Hdr);
  88. auto HeaderContent = G.allocateString(
  89. StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
  90. return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
  91. 0);
  92. }
  93. static MaterializationUnit::Interface
  94. createHeaderInterface(MachOPlatform &MOP,
  95. const SymbolStringPtr &HeaderStartSymbol) {
  96. SymbolFlagsMap HeaderSymbolFlags;
  97. HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
  98. for (auto &HS : AdditionalHeaderSymbols)
  99. HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
  100. JITSymbolFlags::Exported;
  101. return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
  102. HeaderStartSymbol);
  103. }
  104. MachOPlatform &MOP;
  105. };
  106. constexpr MachOHeaderMaterializationUnit::HeaderSymbol
  107. MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
  108. StringRef EHFrameSectionName = "__TEXT,__eh_frame";
  109. StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
  110. StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
  111. StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
  112. StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
  113. StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
  114. StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
  115. StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
  116. StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
  117. StringRef ThreadDataSectionName = "__DATA,__thread_data";
  118. StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
  119. StringRef InitSectionNames[] = {
  120. ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
  121. Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
  122. } // end anonymous namespace
  123. namespace llvm {
  124. namespace orc {
  125. Expected<std::unique_ptr<MachOPlatform>>
  126. MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  127. JITDylib &PlatformJD, const char *OrcRuntimePath,
  128. Optional<SymbolAliasMap> RuntimeAliases) {
  129. auto &EPC = ES.getExecutorProcessControl();
  130. // If the target is not supported then bail out immediately.
  131. if (!supportedTarget(EPC.getTargetTriple()))
  132. return make_error<StringError>("Unsupported MachOPlatform triple: " +
  133. EPC.getTargetTriple().str(),
  134. inconvertibleErrorCode());
  135. // Create default aliases if the caller didn't supply any.
  136. if (!RuntimeAliases)
  137. RuntimeAliases = standardPlatformAliases(ES);
  138. // Define the aliases.
  139. if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
  140. return std::move(Err);
  141. // Add JIT-dispatch function support symbols.
  142. if (auto Err = PlatformJD.define(absoluteSymbols(
  143. {{ES.intern("___orc_rt_jit_dispatch"),
  144. {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
  145. JITSymbolFlags::Exported}},
  146. {ES.intern("___orc_rt_jit_dispatch_ctx"),
  147. {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
  148. JITSymbolFlags::Exported}}})))
  149. return std::move(Err);
  150. // Create a generator for the ORC runtime archive.
  151. auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
  152. ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
  153. if (!OrcRuntimeArchiveGenerator)
  154. return OrcRuntimeArchiveGenerator.takeError();
  155. // Create the instance.
  156. Error Err = Error::success();
  157. auto P = std::unique_ptr<MachOPlatform>(
  158. new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
  159. std::move(*OrcRuntimeArchiveGenerator), Err));
  160. if (Err)
  161. return std::move(Err);
  162. return std::move(P);
  163. }
  164. Error MachOPlatform::setupJITDylib(JITDylib &JD) {
  165. return JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
  166. *this, MachOHeaderStartSymbol));
  167. }
  168. Error MachOPlatform::teardownJITDylib(JITDylib &JD) { return Error::success(); }
  169. Error MachOPlatform::notifyAdding(ResourceTracker &RT,
  170. const MaterializationUnit &MU) {
  171. auto &JD = RT.getJITDylib();
  172. const auto &InitSym = MU.getInitializerSymbol();
  173. if (!InitSym)
  174. return Error::success();
  175. RegisteredInitSymbols[&JD].add(InitSym,
  176. SymbolLookupFlags::WeaklyReferencedSymbol);
  177. LLVM_DEBUG({
  178. dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
  179. << MU.getName() << "\n";
  180. });
  181. return Error::success();
  182. }
  183. Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
  184. llvm_unreachable("Not supported yet");
  185. }
  186. static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
  187. ArrayRef<std::pair<const char *, const char *>> AL) {
  188. for (auto &KV : AL) {
  189. auto AliasName = ES.intern(KV.first);
  190. assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
  191. Aliases[std::move(AliasName)] = {ES.intern(KV.second),
  192. JITSymbolFlags::Exported};
  193. }
  194. }
  195. SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {
  196. SymbolAliasMap Aliases;
  197. addAliases(ES, Aliases, requiredCXXAliases());
  198. addAliases(ES, Aliases, standardRuntimeUtilityAliases());
  199. return Aliases;
  200. }
  201. ArrayRef<std::pair<const char *, const char *>>
  202. MachOPlatform::requiredCXXAliases() {
  203. static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
  204. {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
  205. return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
  206. }
  207. ArrayRef<std::pair<const char *, const char *>>
  208. MachOPlatform::standardRuntimeUtilityAliases() {
  209. static const std::pair<const char *, const char *>
  210. StandardRuntimeUtilityAliases[] = {
  211. {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
  212. {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
  213. return ArrayRef<std::pair<const char *, const char *>>(
  214. StandardRuntimeUtilityAliases);
  215. }
  216. bool MachOPlatform::isInitializerSection(StringRef SegName,
  217. StringRef SectName) {
  218. for (auto &Name : InitSectionNames) {
  219. if (Name.startswith(SegName) && Name.substr(7) == SectName)
  220. return true;
  221. }
  222. return false;
  223. }
  224. bool MachOPlatform::supportedTarget(const Triple &TT) {
  225. switch (TT.getArch()) {
  226. case Triple::aarch64:
  227. case Triple::x86_64:
  228. return true;
  229. default:
  230. return false;
  231. }
  232. }
  233. MachOPlatform::MachOPlatform(
  234. ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  235. JITDylib &PlatformJD,
  236. std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
  237. : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
  238. MachOHeaderStartSymbol(ES.intern("___dso_handle")) {
  239. ErrorAsOutParameter _(&Err);
  240. ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
  241. PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
  242. // Force linking of eh-frame registration functions.
  243. if (auto Err2 = lookupAndRecordAddrs(
  244. ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
  245. {{ES.intern("___orc_rt_macho_register_ehframe_section"),
  246. &orc_rt_macho_register_ehframe_section},
  247. {ES.intern("___orc_rt_macho_deregister_ehframe_section"),
  248. &orc_rt_macho_deregister_ehframe_section}})) {
  249. Err = std::move(Err2);
  250. return;
  251. }
  252. State = BootstrapPhase2;
  253. // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating
  254. // the platform now), so set it up.
  255. if (auto E2 = setupJITDylib(PlatformJD)) {
  256. Err = std::move(E2);
  257. return;
  258. }
  259. RegisteredInitSymbols[&PlatformJD].add(
  260. MachOHeaderStartSymbol, SymbolLookupFlags::WeaklyReferencedSymbol);
  261. // Associate wrapper function tags with JIT-side function implementations.
  262. if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
  263. Err = std::move(E2);
  264. return;
  265. }
  266. // Lookup addresses of runtime functions callable by the platform,
  267. // call the platform bootstrap function to initialize the platform-state
  268. // object in the executor.
  269. if (auto E2 = bootstrapMachORuntime(PlatformJD)) {
  270. Err = std::move(E2);
  271. return;
  272. }
  273. State = Initialized;
  274. }
  275. Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
  276. ExecutionSession::JITDispatchHandlerAssociationMap WFs;
  277. using GetInitializersSPSSig =
  278. SPSExpected<SPSMachOJITDylibInitializerSequence>(SPSString);
  279. WFs[ES.intern("___orc_rt_macho_get_initializers_tag")] =
  280. ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
  281. this, &MachOPlatform::rt_getInitializers);
  282. using GetDeinitializersSPSSig =
  283. SPSExpected<SPSMachOJITDylibDeinitializerSequence>(SPSExecutorAddr);
  284. WFs[ES.intern("___orc_rt_macho_get_deinitializers_tag")] =
  285. ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
  286. this, &MachOPlatform::rt_getDeinitializers);
  287. using LookupSymbolSPSSig =
  288. SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
  289. WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
  290. ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
  291. &MachOPlatform::rt_lookupSymbol);
  292. return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
  293. }
  294. void MachOPlatform::getInitializersBuildSequencePhase(
  295. SendInitializerSequenceFn SendResult, JITDylib &JD,
  296. std::vector<JITDylibSP> DFSLinkOrder) {
  297. MachOJITDylibInitializerSequence FullInitSeq;
  298. {
  299. std::lock_guard<std::mutex> Lock(PlatformMutex);
  300. for (auto &InitJD : reverse(DFSLinkOrder)) {
  301. LLVM_DEBUG({
  302. dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName()
  303. << "\" to sequence\n";
  304. });
  305. auto ISItr = InitSeqs.find(InitJD.get());
  306. if (ISItr != InitSeqs.end()) {
  307. FullInitSeq.emplace_back(std::move(ISItr->second));
  308. InitSeqs.erase(ISItr);
  309. }
  310. }
  311. }
  312. SendResult(std::move(FullInitSeq));
  313. }
  314. void MachOPlatform::getInitializersLookupPhase(
  315. SendInitializerSequenceFn SendResult, JITDylib &JD) {
  316. auto DFSLinkOrder = JD.getDFSLinkOrder();
  317. if (!DFSLinkOrder) {
  318. SendResult(DFSLinkOrder.takeError());
  319. return;
  320. }
  321. DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
  322. ES.runSessionLocked([&]() {
  323. for (auto &InitJD : *DFSLinkOrder) {
  324. auto RISItr = RegisteredInitSymbols.find(InitJD.get());
  325. if (RISItr != RegisteredInitSymbols.end()) {
  326. NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
  327. RegisteredInitSymbols.erase(RISItr);
  328. }
  329. }
  330. });
  331. // If there are no further init symbols to look up then move on to the next
  332. // phase.
  333. if (NewInitSymbols.empty()) {
  334. getInitializersBuildSequencePhase(std::move(SendResult), JD,
  335. std::move(*DFSLinkOrder));
  336. return;
  337. }
  338. // Otherwise issue a lookup and re-run this phase when it completes.
  339. lookupInitSymbolsAsync(
  340. [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
  341. if (Err)
  342. SendResult(std::move(Err));
  343. else
  344. getInitializersLookupPhase(std::move(SendResult), JD);
  345. },
  346. ES, std::move(NewInitSymbols));
  347. }
  348. void MachOPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
  349. StringRef JDName) {
  350. LLVM_DEBUG({
  351. dbgs() << "MachOPlatform::rt_getInitializers(\"" << JDName << "\")\n";
  352. });
  353. JITDylib *JD = ES.getJITDylibByName(JDName);
  354. if (!JD) {
  355. LLVM_DEBUG({
  356. dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n";
  357. });
  358. SendResult(make_error<StringError>("No JITDylib named " + JDName,
  359. inconvertibleErrorCode()));
  360. return;
  361. }
  362. getInitializersLookupPhase(std::move(SendResult), *JD);
  363. }
  364. void MachOPlatform::rt_getDeinitializers(SendDeinitializerSequenceFn SendResult,
  365. ExecutorAddr Handle) {
  366. LLVM_DEBUG({
  367. dbgs() << "MachOPlatform::rt_getDeinitializers(\""
  368. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  369. });
  370. JITDylib *JD = nullptr;
  371. {
  372. std::lock_guard<std::mutex> Lock(PlatformMutex);
  373. auto I = HeaderAddrToJITDylib.find(Handle);
  374. if (I != HeaderAddrToJITDylib.end())
  375. JD = I->second;
  376. }
  377. if (!JD) {
  378. LLVM_DEBUG({
  379. dbgs() << " No JITDylib for handle "
  380. << formatv("{0:x}", Handle.getValue()) << "\n";
  381. });
  382. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  383. formatv("{0:x}", Handle.getValue()),
  384. inconvertibleErrorCode()));
  385. return;
  386. }
  387. SendResult(MachOJITDylibDeinitializerSequence());
  388. }
  389. void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
  390. ExecutorAddr Handle, StringRef SymbolName) {
  391. LLVM_DEBUG({
  392. dbgs() << "MachOPlatform::rt_lookupSymbol(\""
  393. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  394. });
  395. JITDylib *JD = nullptr;
  396. {
  397. std::lock_guard<std::mutex> Lock(PlatformMutex);
  398. auto I = HeaderAddrToJITDylib.find(Handle);
  399. if (I != HeaderAddrToJITDylib.end())
  400. JD = I->second;
  401. }
  402. if (!JD) {
  403. LLVM_DEBUG({
  404. dbgs() << " No JITDylib for handle "
  405. << formatv("{0:x}", Handle.getValue()) << "\n";
  406. });
  407. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  408. formatv("{0:x}", Handle.getValue()),
  409. inconvertibleErrorCode()));
  410. return;
  411. }
  412. // Use functor class to work around XL build compiler issue on AIX.
  413. class RtLookupNotifyComplete {
  414. public:
  415. RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
  416. : SendResult(std::move(SendResult)) {}
  417. void operator()(Expected<SymbolMap> Result) {
  418. if (Result) {
  419. assert(Result->size() == 1 && "Unexpected result map count");
  420. SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
  421. } else {
  422. SendResult(Result.takeError());
  423. }
  424. }
  425. private:
  426. SendSymbolAddressFn SendResult;
  427. };
  428. // FIXME: Proper mangling.
  429. auto MangledName = ("_" + SymbolName).str();
  430. ES.lookup(
  431. LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
  432. SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
  433. RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
  434. }
  435. Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
  436. if (auto Err = lookupAndRecordAddrs(
  437. ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
  438. {{ES.intern("___orc_rt_macho_platform_bootstrap"),
  439. &orc_rt_macho_platform_bootstrap},
  440. {ES.intern("___orc_rt_macho_platform_shutdown"),
  441. &orc_rt_macho_platform_shutdown},
  442. {ES.intern("___orc_rt_macho_register_thread_data_section"),
  443. &orc_rt_macho_register_thread_data_section},
  444. {ES.intern("___orc_rt_macho_deregister_thread_data_section"),
  445. &orc_rt_macho_deregister_thread_data_section},
  446. {ES.intern("___orc_rt_macho_create_pthread_key"),
  447. &orc_rt_macho_create_pthread_key}}))
  448. return Err;
  449. return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap);
  450. }
  451. Error MachOPlatform::registerInitInfo(
  452. JITDylib &JD, ExecutorAddr ObjCImageInfoAddr,
  453. ArrayRef<jitlink::Section *> InitSections) {
  454. std::unique_lock<std::mutex> Lock(PlatformMutex);
  455. MachOJITDylibInitializers *InitSeq = nullptr;
  456. {
  457. auto I = InitSeqs.find(&JD);
  458. if (I == InitSeqs.end()) {
  459. // If there's no init sequence entry yet then we need to look up the
  460. // header symbol to force creation of one.
  461. Lock.unlock();
  462. auto SearchOrder =
  463. JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; });
  464. if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError())
  465. return Err;
  466. Lock.lock();
  467. I = InitSeqs.find(&JD);
  468. assert(I != InitSeqs.end() &&
  469. "Entry missing after header symbol lookup?");
  470. }
  471. InitSeq = &I->second;
  472. }
  473. InitSeq->ObjCImageInfoAddress = ObjCImageInfoAddr;
  474. for (auto *Sec : InitSections) {
  475. // FIXME: Avoid copy here.
  476. jitlink::SectionRange R(*Sec);
  477. InitSeq->InitSections[Sec->getName()].push_back(
  478. {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())});
  479. }
  480. return Error::success();
  481. }
  482. Expected<uint64_t> MachOPlatform::createPThreadKey() {
  483. if (!orc_rt_macho_create_pthread_key)
  484. return make_error<StringError>(
  485. "Attempting to create pthread key in target, but runtime support has "
  486. "not been loaded yet",
  487. inconvertibleErrorCode());
  488. Expected<uint64_t> Result(0);
  489. if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
  490. orc_rt_macho_create_pthread_key, Result))
  491. return std::move(Err);
  492. return Result;
  493. }
  494. void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
  495. MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
  496. jitlink::PassConfiguration &Config) {
  497. auto PS = MP.State.load();
  498. // --- Handle Initializers ---
  499. if (auto InitSymbol = MR.getInitializerSymbol()) {
  500. // If the initializer symbol is the MachOHeader start symbol then just
  501. // register it and then bail out -- the header materialization unit
  502. // definitely doesn't need any other passes.
  503. if (InitSymbol == MP.MachOHeaderStartSymbol) {
  504. Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) {
  505. return associateJITDylibHeaderSymbol(G, MR);
  506. });
  507. return;
  508. }
  509. // If the object contains an init symbol other than the header start symbol
  510. // then add passes to preserve, process and register the init
  511. // sections/symbols.
  512. Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
  513. if (auto Err = preserveInitSections(G, MR))
  514. return Err;
  515. return processObjCImageInfo(G, MR);
  516. });
  517. Config.PostFixupPasses.push_back(
  518. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  519. return registerInitSections(G, JD);
  520. });
  521. }
  522. // --- Add passes for eh-frame and TLV support ---
  523. if (PS == MachOPlatform::BootstrapPhase1) {
  524. Config.PostFixupPasses.push_back(
  525. [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); });
  526. return;
  527. }
  528. // Insert TLV lowering at the start of the PostPrunePasses, since we want
  529. // it to run before GOT/PLT lowering.
  530. Config.PostPrunePasses.insert(
  531. Config.PostPrunePasses.begin(),
  532. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  533. return fixTLVSectionsAndEdges(G, JD);
  534. });
  535. // Add a pass to register the final addresses of the eh-frame and TLV sections
  536. // with the runtime.
  537. Config.PostFixupPasses.push_back(
  538. [this](jitlink::LinkGraph &G) { return registerEHAndTLVSections(G); });
  539. }
  540. ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
  541. MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
  542. MaterializationResponsibility &MR) {
  543. std::lock_guard<std::mutex> Lock(PluginMutex);
  544. auto I = InitSymbolDeps.find(&MR);
  545. if (I != InitSymbolDeps.end()) {
  546. SyntheticSymbolDependenciesMap Result;
  547. Result[MR.getInitializerSymbol()] = std::move(I->second);
  548. InitSymbolDeps.erase(&MR);
  549. return Result;
  550. }
  551. return SyntheticSymbolDependenciesMap();
  552. }
  553. Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
  554. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  555. auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
  556. return Sym->getName() == *MP.MachOHeaderStartSymbol;
  557. });
  558. assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
  559. auto &JD = MR.getTargetJITDylib();
  560. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  561. auto HeaderAddr = (*I)->getAddress();
  562. MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
  563. assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists");
  564. MP.InitSeqs.insert(
  565. std::make_pair(&JD, MachOJITDylibInitializers(JD.getName(), HeaderAddr)));
  566. return Error::success();
  567. }
  568. Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
  569. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  570. JITLinkSymbolSet InitSectionSymbols;
  571. for (auto &InitSectionName : InitSectionNames) {
  572. // Skip non-init sections.
  573. auto *InitSection = G.findSectionByName(InitSectionName);
  574. if (!InitSection)
  575. continue;
  576. // Make a pass over live symbols in the section: those blocks are already
  577. // preserved.
  578. DenseSet<jitlink::Block *> AlreadyLiveBlocks;
  579. for (auto &Sym : InitSection->symbols()) {
  580. auto &B = Sym->getBlock();
  581. if (Sym->isLive() && Sym->getOffset() == 0 &&
  582. Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
  583. InitSectionSymbols.insert(Sym);
  584. AlreadyLiveBlocks.insert(&B);
  585. }
  586. }
  587. // Add anonymous symbols to preserve any not-already-preserved blocks.
  588. for (auto *B : InitSection->blocks())
  589. if (!AlreadyLiveBlocks.count(B))
  590. InitSectionSymbols.insert(
  591. &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
  592. }
  593. if (!InitSectionSymbols.empty()) {
  594. std::lock_guard<std::mutex> Lock(PluginMutex);
  595. InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
  596. }
  597. return Error::success();
  598. }
  599. Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
  600. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  601. // If there's an ObjC imagine info then either
  602. // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
  603. // this case we name and record it.
  604. // OR
  605. // (2) We already have a recorded __objc_imageinfo for this JITDylib,
  606. // in which case we just verify it.
  607. auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
  608. if (!ObjCImageInfo)
  609. return Error::success();
  610. auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
  611. // Check that the section is not empty if present.
  612. if (llvm::empty(ObjCImageInfoBlocks))
  613. return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
  614. " section in " + G.getName(),
  615. inconvertibleErrorCode());
  616. // Check that there's only one block in the section.
  617. if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
  618. return make_error<StringError>("Multiple blocks in " +
  619. ObjCImageInfoSectionName +
  620. " section in " + G.getName(),
  621. inconvertibleErrorCode());
  622. // Check that the __objc_imageinfo section is unreferenced.
  623. // FIXME: We could optimize this check if Symbols had a ref-count.
  624. for (auto &Sec : G.sections()) {
  625. if (&Sec != ObjCImageInfo)
  626. for (auto *B : Sec.blocks())
  627. for (auto &E : B->edges())
  628. if (E.getTarget().isDefined() &&
  629. &E.getTarget().getBlock().getSection() == ObjCImageInfo)
  630. return make_error<StringError>(ObjCImageInfoSectionName +
  631. " is referenced within file " +
  632. G.getName(),
  633. inconvertibleErrorCode());
  634. }
  635. auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
  636. auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
  637. auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
  638. auto Flags =
  639. support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
  640. // Lock the mutex while we verify / update the ObjCImageInfos map.
  641. std::lock_guard<std::mutex> Lock(PluginMutex);
  642. auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
  643. if (ObjCImageInfoItr != ObjCImageInfos.end()) {
  644. // We've already registered an __objc_imageinfo section. Verify the
  645. // content of this new section matches, then delete it.
  646. if (ObjCImageInfoItr->second.first != Version)
  647. return make_error<StringError>(
  648. "ObjC version in " + G.getName() +
  649. " does not match first registered version",
  650. inconvertibleErrorCode());
  651. if (ObjCImageInfoItr->second.second != Flags)
  652. return make_error<StringError>("ObjC flags in " + G.getName() +
  653. " do not match first registered flags",
  654. inconvertibleErrorCode());
  655. // __objc_imageinfo is valid. Delete the block.
  656. for (auto *S : ObjCImageInfo->symbols())
  657. G.removeDefinedSymbol(*S);
  658. G.removeBlock(ObjCImageInfoBlock);
  659. } else {
  660. // We haven't registered an __objc_imageinfo section yet. Register and
  661. // move on. The section should already be marked no-dead-strip.
  662. ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
  663. }
  664. return Error::success();
  665. }
  666. Error MachOPlatform::MachOPlatformPlugin::registerInitSections(
  667. jitlink::LinkGraph &G, JITDylib &JD) {
  668. ExecutorAddr ObjCImageInfoAddr;
  669. SmallVector<jitlink::Section *> InitSections;
  670. if (auto *ObjCImageInfoSec = G.findSectionByName(ObjCImageInfoSectionName)) {
  671. if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart())
  672. ObjCImageInfoAddr = Addr;
  673. }
  674. for (auto InitSectionName : InitSectionNames)
  675. if (auto *Sec = G.findSectionByName(InitSectionName))
  676. InitSections.push_back(Sec);
  677. // Dump the scraped inits.
  678. LLVM_DEBUG({
  679. dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
  680. if (ObjCImageInfoAddr)
  681. dbgs() << " " << ObjCImageInfoSectionName << ": "
  682. << formatv("{0:x}", ObjCImageInfoAddr.getValue()) << "\n";
  683. for (auto *Sec : InitSections) {
  684. jitlink::SectionRange R(*Sec);
  685. dbgs() << " " << Sec->getName() << ": "
  686. << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n";
  687. }
  688. });
  689. return MP.registerInitInfo(JD, ObjCImageInfoAddr, InitSections);
  690. }
  691. Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
  692. jitlink::LinkGraph &G, JITDylib &JD) {
  693. // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
  694. for (auto *Sym : G.external_symbols())
  695. if (Sym->getName() == "__tlv_bootstrap") {
  696. Sym->setName("___orc_rt_macho_tlv_get_addr");
  697. break;
  698. }
  699. // Store key in __thread_vars struct fields.
  700. if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
  701. Optional<uint64_t> Key;
  702. {
  703. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  704. auto I = MP.JITDylibToPThreadKey.find(&JD);
  705. if (I != MP.JITDylibToPThreadKey.end())
  706. Key = I->second;
  707. }
  708. if (!Key) {
  709. if (auto KeyOrErr = MP.createPThreadKey())
  710. Key = *KeyOrErr;
  711. else
  712. return KeyOrErr.takeError();
  713. }
  714. uint64_t PlatformKeyBits =
  715. support::endian::byte_swap(*Key, G.getEndianness());
  716. for (auto *B : ThreadDataSec->blocks()) {
  717. if (B->getSize() != 3 * G.getPointerSize())
  718. return make_error<StringError>("__thread_vars block at " +
  719. formatv("{0:x}", B->getAddress()) +
  720. " has unexpected size",
  721. inconvertibleErrorCode());
  722. auto NewBlockContent = G.allocateBuffer(B->getSize());
  723. llvm::copy(B->getContent(), NewBlockContent.data());
  724. memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
  725. G.getPointerSize());
  726. B->setContent(NewBlockContent);
  727. }
  728. }
  729. // Transform any TLV edges into GOT edges.
  730. for (auto *B : G.blocks())
  731. for (auto &E : B->edges())
  732. if (E.getKind() ==
  733. jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable)
  734. E.setKind(jitlink::x86_64::
  735. RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
  736. return Error::success();
  737. }
  738. Error MachOPlatform::MachOPlatformPlugin::registerEHAndTLVSections(
  739. jitlink::LinkGraph &G) {
  740. // Add a pass to register the final addresses of the eh-frame and TLV sections
  741. // with the runtime.
  742. if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
  743. jitlink::SectionRange R(*EHFrameSection);
  744. if (!R.empty())
  745. G.allocActions().push_back(
  746. {cantFail(
  747. WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  748. MP.orc_rt_macho_register_ehframe_section, R.getRange())),
  749. cantFail(
  750. WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  751. MP.orc_rt_macho_deregister_ehframe_section, R.getRange()))});
  752. }
  753. // Get a pointer to the thread data section if there is one. It will be used
  754. // below.
  755. jitlink::Section *ThreadDataSection =
  756. G.findSectionByName(ThreadDataSectionName);
  757. // Handle thread BSS section if there is one.
  758. if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
  759. // If there's already a thread data section in this graph then merge the
  760. // thread BSS section content into it, otherwise just treat the thread
  761. // BSS section as the thread data section.
  762. if (ThreadDataSection)
  763. G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
  764. else
  765. ThreadDataSection = ThreadBSSSection;
  766. }
  767. // Having merged thread BSS (if present) and thread data (if present),
  768. // record the resulting section range.
  769. if (ThreadDataSection) {
  770. jitlink::SectionRange R(*ThreadDataSection);
  771. if (!R.empty()) {
  772. if (MP.State != MachOPlatform::Initialized)
  773. return make_error<StringError>("__thread_data section encountered, but "
  774. "MachOPlatform has not finished booting",
  775. inconvertibleErrorCode());
  776. G.allocActions().push_back(
  777. {cantFail(
  778. WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  779. MP.orc_rt_macho_register_thread_data_section, R.getRange())),
  780. cantFail(
  781. WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  782. MP.orc_rt_macho_deregister_thread_data_section,
  783. R.getRange()))});
  784. }
  785. }
  786. return Error::success();
  787. }
  788. Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1(
  789. jitlink::LinkGraph &G) {
  790. // If there's no eh-frame there's nothing to do.
  791. auto *EHFrameSection = G.findSectionByName(EHFrameSectionName);
  792. if (!EHFrameSection)
  793. return Error::success();
  794. // If the eh-frame section is empty there's nothing to do.
  795. jitlink::SectionRange R(*EHFrameSection);
  796. if (R.empty())
  797. return Error::success();
  798. // Since we're linking the object containing the registration code now the
  799. // addresses won't be ready in the platform. We'll have to find them in this
  800. // graph instead.
  801. ExecutorAddr orc_rt_macho_register_ehframe_section;
  802. ExecutorAddr orc_rt_macho_deregister_ehframe_section;
  803. for (auto *Sym : G.defined_symbols()) {
  804. if (!Sym->hasName())
  805. continue;
  806. if (Sym->getName() == "___orc_rt_macho_register_ehframe_section")
  807. orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress());
  808. else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section")
  809. orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress());
  810. if (orc_rt_macho_register_ehframe_section &&
  811. orc_rt_macho_deregister_ehframe_section)
  812. break;
  813. }
  814. // If we failed to find the required functions then bail out.
  815. if (!orc_rt_macho_register_ehframe_section ||
  816. !orc_rt_macho_deregister_ehframe_section)
  817. return make_error<StringError>("Could not find eh-frame registration "
  818. "functions during platform bootstrap",
  819. inconvertibleErrorCode());
  820. // Otherwise, add allocation actions to the graph to register eh-frames for
  821. // this object.
  822. G.allocActions().push_back(
  823. {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  824. orc_rt_macho_register_ehframe_section, R.getRange())),
  825. cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
  826. orc_rt_macho_deregister_ehframe_section, R.getRange()))});
  827. return Error::success();
  828. }
  829. } // End namespace orc.
  830. } // End namespace llvm.