MachOPlatform.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
  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. #include <optional>
  17. #define DEBUG_TYPE "orc"
  18. using namespace llvm;
  19. using namespace llvm::orc;
  20. using namespace llvm::orc::shared;
  21. namespace llvm {
  22. namespace orc {
  23. namespace shared {
  24. using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;
  25. using SPSMachOJITDylibDepInfoMap =
  26. SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;
  27. template <>
  28. class SPSSerializationTraits<SPSMachOJITDylibDepInfo,
  29. MachOPlatform::MachOJITDylibDepInfo> {
  30. public:
  31. static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
  32. return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
  33. }
  34. static bool serialize(SPSOutputBuffer &OB,
  35. const MachOPlatform::MachOJITDylibDepInfo &DDI) {
  36. return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
  37. DDI.DepHeaders);
  38. }
  39. static bool deserialize(SPSInputBuffer &IB,
  40. MachOPlatform::MachOJITDylibDepInfo &DDI) {
  41. return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
  42. DDI.DepHeaders);
  43. }
  44. };
  45. } // namespace shared
  46. } // namespace orc
  47. } // namespace llvm
  48. namespace {
  49. std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
  50. std::string Name) {
  51. unsigned PointerSize;
  52. support::endianness Endianness;
  53. const auto &TT =
  54. MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
  55. switch (TT.getArch()) {
  56. case Triple::aarch64:
  57. case Triple::x86_64:
  58. PointerSize = 8;
  59. Endianness = support::endianness::little;
  60. break;
  61. default:
  62. llvm_unreachable("Unrecognized architecture");
  63. }
  64. return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize,
  65. Endianness,
  66. jitlink::getGenericEdgeKindName);
  67. }
  68. // Generates a MachO header.
  69. class MachOHeaderMaterializationUnit : public MaterializationUnit {
  70. public:
  71. MachOHeaderMaterializationUnit(MachOPlatform &MOP,
  72. const SymbolStringPtr &HeaderStartSymbol)
  73. : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
  74. MOP(MOP) {}
  75. StringRef getName() const override { return "MachOHeaderMU"; }
  76. void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
  77. auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
  78. addMachOHeader(*G, MOP, R->getInitializerSymbol());
  79. MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  80. }
  81. void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
  82. static void addMachOHeader(jitlink::LinkGraph &G, MachOPlatform &MOP,
  83. const SymbolStringPtr &InitializerSymbol) {
  84. auto &HeaderSection = G.createSection("__header", MemProt::Read);
  85. auto &HeaderBlock = createHeaderBlock(G, HeaderSection);
  86. // Init symbol is header-start symbol.
  87. G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol,
  88. HeaderBlock.getSize(), jitlink::Linkage::Strong,
  89. jitlink::Scope::Default, false, true);
  90. for (auto &HS : AdditionalHeaderSymbols)
  91. G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
  92. jitlink::Linkage::Strong, jitlink::Scope::Default,
  93. false, true);
  94. }
  95. private:
  96. struct HeaderSymbol {
  97. const char *Name;
  98. uint64_t Offset;
  99. };
  100. static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
  101. {"___mh_executable_header", 0}};
  102. static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
  103. jitlink::Section &HeaderSection) {
  104. MachO::mach_header_64 Hdr;
  105. Hdr.magic = MachO::MH_MAGIC_64;
  106. switch (G.getTargetTriple().getArch()) {
  107. case Triple::aarch64:
  108. Hdr.cputype = MachO::CPU_TYPE_ARM64;
  109. Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
  110. break;
  111. case Triple::x86_64:
  112. Hdr.cputype = MachO::CPU_TYPE_X86_64;
  113. Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
  114. break;
  115. default:
  116. llvm_unreachable("Unrecognized architecture");
  117. }
  118. Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
  119. Hdr.ncmds = 0;
  120. Hdr.sizeofcmds = 0;
  121. Hdr.flags = 0;
  122. Hdr.reserved = 0;
  123. if (G.getEndianness() != support::endian::system_endianness())
  124. MachO::swapStruct(Hdr);
  125. auto HeaderContent = G.allocateString(
  126. StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
  127. return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
  128. 0);
  129. }
  130. static MaterializationUnit::Interface
  131. createHeaderInterface(MachOPlatform &MOP,
  132. const SymbolStringPtr &HeaderStartSymbol) {
  133. SymbolFlagsMap HeaderSymbolFlags;
  134. HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
  135. for (auto &HS : AdditionalHeaderSymbols)
  136. HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
  137. JITSymbolFlags::Exported;
  138. return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
  139. HeaderStartSymbol);
  140. }
  141. MachOPlatform &MOP;
  142. };
  143. constexpr MachOHeaderMaterializationUnit::HeaderSymbol
  144. MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
  145. // Creates a Bootstrap-Complete LinkGraph to run deferred actions.
  146. class MachOPlatformCompleteBootstrapMaterializationUnit
  147. : public MaterializationUnit {
  148. public:
  149. MachOPlatformCompleteBootstrapMaterializationUnit(
  150. MachOPlatform &MOP, StringRef PlatformJDName,
  151. SymbolStringPtr CompleteBootstrapSymbol, shared::AllocActions DeferredAAs,
  152. ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
  153. ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
  154. ExecutorAddr MachOHeaderAddr)
  155. : MaterializationUnit(
  156. {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),
  157. MOP(MOP), PlatformJDName(PlatformJDName),
  158. CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
  159. DeferredAAs(std::move(DeferredAAs)),
  160. PlatformBootstrap(PlatformBootstrap),
  161. PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
  162. DeregisterJITDylib(DeregisterJITDylib),
  163. MachOHeaderAddr(MachOHeaderAddr) {}
  164. StringRef getName() const override {
  165. return "MachOPlatformCompleteBootstrap";
  166. }
  167. void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
  168. using namespace jitlink;
  169. auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>");
  170. auto &PlaceholderSection =
  171. G->createSection("__orc_rt_cplt_bs", MemProt::Read);
  172. auto &PlaceholderBlock =
  173. G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);
  174. G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
  175. Linkage::Strong, Scope::Hidden, false, true);
  176. // Reserve space for the stolen actions, plus two extras.
  177. G->allocActions().reserve(DeferredAAs.size() + 2);
  178. // 1. Bootstrap the platform support code.
  179. G->allocActions().push_back(
  180. {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)),
  181. cantFail(
  182. WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))});
  183. // 2. Register the platform JITDylib.
  184. G->allocActions().push_back(
  185. {cantFail(WrapperFunctionCall::Create<
  186. SPSArgList<SPSString, SPSExecutorAddr>>(
  187. RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
  188. cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
  189. DeregisterJITDylib, MachOHeaderAddr))});
  190. // 3. Add the deferred actions to the graph.
  191. std::move(DeferredAAs.begin(), DeferredAAs.end(),
  192. std::back_inserter(G->allocActions()));
  193. MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  194. }
  195. void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
  196. private:
  197. MachOPlatform &MOP;
  198. StringRef PlatformJDName;
  199. SymbolStringPtr CompleteBootstrapSymbol;
  200. shared::AllocActions DeferredAAs;
  201. ExecutorAddr PlatformBootstrap;
  202. ExecutorAddr PlatformShutdown;
  203. ExecutorAddr RegisterJITDylib;
  204. ExecutorAddr DeregisterJITDylib;
  205. ExecutorAddr MachOHeaderAddr;
  206. };
  207. StringRef DataCommonSectionName = "__DATA,__common";
  208. StringRef DataDataSectionName = "__DATA,__data";
  209. StringRef EHFrameSectionName = "__TEXT,__eh_frame";
  210. StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
  211. StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
  212. StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
  213. StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
  214. StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
  215. StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
  216. StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
  217. StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
  218. StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
  219. StringRef ThreadDataSectionName = "__DATA,__thread_data";
  220. StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
  221. StringRef InitSectionNames[] = {
  222. ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
  223. Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
  224. } // end anonymous namespace
  225. namespace llvm {
  226. namespace orc {
  227. Expected<std::unique_ptr<MachOPlatform>>
  228. MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  229. JITDylib &PlatformJD, const char *OrcRuntimePath,
  230. std::optional<SymbolAliasMap> RuntimeAliases) {
  231. auto &EPC = ES.getExecutorProcessControl();
  232. // If the target is not supported then bail out immediately.
  233. if (!supportedTarget(EPC.getTargetTriple()))
  234. return make_error<StringError>("Unsupported MachOPlatform triple: " +
  235. EPC.getTargetTriple().str(),
  236. inconvertibleErrorCode());
  237. // Create default aliases if the caller didn't supply any.
  238. if (!RuntimeAliases)
  239. RuntimeAliases = standardPlatformAliases(ES);
  240. // Define the aliases.
  241. if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
  242. return std::move(Err);
  243. // Add JIT-dispatch function support symbols.
  244. if (auto Err = PlatformJD.define(absoluteSymbols(
  245. {{ES.intern("___orc_rt_jit_dispatch"),
  246. {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
  247. JITSymbolFlags::Exported}},
  248. {ES.intern("___orc_rt_jit_dispatch_ctx"),
  249. {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
  250. JITSymbolFlags::Exported}}})))
  251. return std::move(Err);
  252. // Create a generator for the ORC runtime archive.
  253. auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
  254. ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
  255. if (!OrcRuntimeArchiveGenerator)
  256. return OrcRuntimeArchiveGenerator.takeError();
  257. // Create the instance.
  258. Error Err = Error::success();
  259. auto P = std::unique_ptr<MachOPlatform>(
  260. new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
  261. std::move(*OrcRuntimeArchiveGenerator), Err));
  262. if (Err)
  263. return std::move(Err);
  264. return std::move(P);
  265. }
  266. Error MachOPlatform::setupJITDylib(JITDylib &JD) {
  267. if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
  268. *this, MachOHeaderStartSymbol)))
  269. return Err;
  270. return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
  271. }
  272. Error MachOPlatform::teardownJITDylib(JITDylib &JD) {
  273. std::lock_guard<std::mutex> Lock(PlatformMutex);
  274. auto I = JITDylibToHeaderAddr.find(&JD);
  275. if (I != JITDylibToHeaderAddr.end()) {
  276. assert(HeaderAddrToJITDylib.count(I->second) &&
  277. "HeaderAddrToJITDylib missing entry");
  278. HeaderAddrToJITDylib.erase(I->second);
  279. JITDylibToHeaderAddr.erase(I);
  280. }
  281. JITDylibToPThreadKey.erase(&JD);
  282. return Error::success();
  283. }
  284. Error MachOPlatform::notifyAdding(ResourceTracker &RT,
  285. const MaterializationUnit &MU) {
  286. auto &JD = RT.getJITDylib();
  287. const auto &InitSym = MU.getInitializerSymbol();
  288. if (!InitSym)
  289. return Error::success();
  290. RegisteredInitSymbols[&JD].add(InitSym,
  291. SymbolLookupFlags::WeaklyReferencedSymbol);
  292. LLVM_DEBUG({
  293. dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
  294. << MU.getName() << "\n";
  295. });
  296. return Error::success();
  297. }
  298. Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
  299. llvm_unreachable("Not supported yet");
  300. }
  301. static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
  302. ArrayRef<std::pair<const char *, const char *>> AL) {
  303. for (auto &KV : AL) {
  304. auto AliasName = ES.intern(KV.first);
  305. assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
  306. Aliases[std::move(AliasName)] = {ES.intern(KV.second),
  307. JITSymbolFlags::Exported};
  308. }
  309. }
  310. SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {
  311. SymbolAliasMap Aliases;
  312. addAliases(ES, Aliases, requiredCXXAliases());
  313. addAliases(ES, Aliases, standardRuntimeUtilityAliases());
  314. return Aliases;
  315. }
  316. ArrayRef<std::pair<const char *, const char *>>
  317. MachOPlatform::requiredCXXAliases() {
  318. static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
  319. {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
  320. return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
  321. }
  322. ArrayRef<std::pair<const char *, const char *>>
  323. MachOPlatform::standardRuntimeUtilityAliases() {
  324. static const std::pair<const char *, const char *>
  325. StandardRuntimeUtilityAliases[] = {
  326. {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
  327. {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
  328. {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
  329. {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
  330. {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
  331. {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
  332. return ArrayRef<std::pair<const char *, const char *>>(
  333. StandardRuntimeUtilityAliases);
  334. }
  335. bool MachOPlatform::isInitializerSection(StringRef SegName,
  336. StringRef SectName) {
  337. for (auto &Name : InitSectionNames) {
  338. if (Name.startswith(SegName) && Name.substr(7) == SectName)
  339. return true;
  340. }
  341. return false;
  342. }
  343. bool MachOPlatform::supportedTarget(const Triple &TT) {
  344. switch (TT.getArch()) {
  345. case Triple::aarch64:
  346. case Triple::x86_64:
  347. return true;
  348. default:
  349. return false;
  350. }
  351. }
  352. MachOPlatform::MachOPlatform(
  353. ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  354. JITDylib &PlatformJD,
  355. std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
  356. : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) {
  357. ErrorAsOutParameter _(&Err);
  358. ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
  359. PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
  360. BootstrapInfo BI;
  361. Bootstrap = &BI;
  362. // Bootstrap process -- here be phase-ordering dragons.
  363. //
  364. // The MachOPlatform class uses allocation actions to register metadata
  365. // sections with the ORC runtime, however the runtime contains metadata
  366. // registration functions that have their own metadata that they need to
  367. // register (e.g. the frame-info registration functions have frame-info).
  368. // We can't use an ordinary lookup to find these registration functions
  369. // because their address is needed during the link of the containing graph
  370. // itself (to build the allocation actions that will call the registration
  371. // functions). Further complicating the situation (a) the graph containing
  372. // the registration functions is allowed to depend on other graphs (e.g. the
  373. // graph containing the ORC runtime RTTI support) so we need to handle with
  374. // an unknown set of dependencies during bootstrap, and (b) these graphs may
  375. // be linked concurrently if the user has installed a concurrent dispatcher.
  376. //
  377. // We satisfy these constraint by implementing a bootstrap phase during which
  378. // allocation actions generated by MachOPlatform are appended to a list of
  379. // deferred allocation actions, rather than to the graphs themselves. At the
  380. // end of the bootstrap process the deferred actions are attached to a final
  381. // "complete-bootstrap" graph that causes them to be run.
  382. //
  383. // The bootstrap steps are as follows:
  384. //
  385. // 1. Request the graph containing the mach header. This graph is guaranteed
  386. // not to have any metadata so the fact that the registration functions
  387. // are not available yet is not a problem.
  388. //
  389. // 2. Look up the registration functions and discard the results. This will
  390. // trigger linking of the graph containing these functions, and
  391. // consequently any graphs that it depends on. We do not use the lookup
  392. // result to find the addresses of the functions requested (as described
  393. // above the lookup will return too late for that), instead we capture the
  394. // addresses in a post-allocation pass injected by the platform runtime
  395. // during bootstrap only.
  396. //
  397. // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of
  398. // graphs being linked (potentially concurrently), and we block until all
  399. // of these graphs have completed linking. This is to avoid a race on the
  400. // deferred-actions vector: the lookup for the runtime registration
  401. // functions may return while some functions (those that are being
  402. // incidentally linked in, but aren't reachable via the runtime functions)
  403. // are still being linked, and we need to capture any allocation actions
  404. // for this incidental code before we proceed.
  405. //
  406. // 4. Once all active links are complete we transfer the deferred actions to
  407. // a newly added CompleteBootstrap graph and then request a symbol from
  408. // the CompleteBootstrap graph to trigger materialization. This will cause
  409. // all deferred actions to be run, and once this lookup returns we can
  410. // proceed.
  411. //
  412. // 5. Finally, we associate runtime support methods in MachOPlatform with
  413. // the corresponding jit-dispatch tag variables in the ORC runtime to make
  414. // the support methods callable. The bootstrap is now complete.
  415. // Step (1) Add header materialization unit and request.
  416. if ((Err = PlatformJD.define(std::make_unique<MachOHeaderMaterializationUnit>(
  417. *this, MachOHeaderStartSymbol))))
  418. return;
  419. if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
  420. return;
  421. // Step (2) Request runtime registration functions to trigger
  422. // materialization..
  423. if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
  424. SymbolLookupSet(
  425. {PlatformBootstrap.Name, PlatformShutdown.Name,
  426. RegisterJITDylib.Name, DeregisterJITDylib.Name,
  427. RegisterObjectPlatformSections.Name,
  428. DeregisterObjectPlatformSections.Name,
  429. CreatePThreadKey.Name}))
  430. .takeError()))
  431. return;
  432. // Step (3) Wait for any incidental linker work to complete.
  433. {
  434. std::unique_lock<std::mutex> Lock(BI.Mutex);
  435. BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });
  436. Bootstrap = nullptr;
  437. }
  438. // Step (4) Add complete-bootstrap materialization unit and request.
  439. auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");
  440. if ((Err = PlatformJD.define(
  441. std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
  442. *this, PlatformJD.getName(), BootstrapCompleteSymbol,
  443. std::move(BI.DeferredAAs), PlatformBootstrap.Addr,
  444. PlatformShutdown.Addr, RegisterJITDylib.Addr,
  445. DeregisterJITDylib.Addr, BI.MachOHeaderAddr))))
  446. return;
  447. if ((Err = ES.lookup(makeJITDylibSearchOrder(
  448. &PlatformJD, JITDylibLookupFlags::MatchAllSymbols),
  449. std::move(BootstrapCompleteSymbol))
  450. .takeError()))
  451. return;
  452. // (5) Associate runtime support functions.
  453. if ((Err = associateRuntimeSupportFunctions()))
  454. return;
  455. }
  456. Error MachOPlatform::associateRuntimeSupportFunctions() {
  457. ExecutionSession::JITDispatchHandlerAssociationMap WFs;
  458. using PushInitializersSPSSig =
  459. SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr);
  460. WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =
  461. ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
  462. this, &MachOPlatform::rt_pushInitializers);
  463. using LookupSymbolSPSSig =
  464. SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
  465. WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
  466. ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
  467. &MachOPlatform::rt_lookupSymbol);
  468. return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
  469. }
  470. void MachOPlatform::pushInitializersLoop(
  471. PushInitializersSendResultFn SendResult, JITDylibSP JD) {
  472. DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
  473. DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;
  474. SmallVector<JITDylib *, 16> Worklist({JD.get()});
  475. ES.runSessionLocked([&]() {
  476. while (!Worklist.empty()) {
  477. // FIXME: Check for defunct dylibs.
  478. auto DepJD = Worklist.back();
  479. Worklist.pop_back();
  480. // If we've already visited this JITDylib on this iteration then continue.
  481. if (JDDepMap.count(DepJD))
  482. continue;
  483. // Add dep info.
  484. auto &DM = JDDepMap[DepJD];
  485. DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
  486. for (auto &KV : O) {
  487. if (KV.first == DepJD)
  488. continue;
  489. DM.push_back(KV.first);
  490. Worklist.push_back(KV.first);
  491. }
  492. });
  493. // Add any registered init symbols.
  494. auto RISItr = RegisteredInitSymbols.find(DepJD);
  495. if (RISItr != RegisteredInitSymbols.end()) {
  496. NewInitSymbols[DepJD] = std::move(RISItr->second);
  497. RegisteredInitSymbols.erase(RISItr);
  498. }
  499. }
  500. });
  501. // If there are no further init symbols to look up then send the link order
  502. // (as a list of header addresses) to the caller.
  503. if (NewInitSymbols.empty()) {
  504. // To make the list intelligible to the runtime we need to convert all
  505. // JITDylib pointers to their header addresses. Only include JITDylibs
  506. // that appear in the JITDylibToHeaderAddr map (i.e. those that have been
  507. // through setupJITDylib) -- bare JITDylibs aren't managed by the platform.
  508. DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
  509. HeaderAddrs.reserve(JDDepMap.size());
  510. {
  511. std::lock_guard<std::mutex> Lock(PlatformMutex);
  512. for (auto &KV : JDDepMap) {
  513. auto I = JITDylibToHeaderAddr.find(KV.first);
  514. if (I != JITDylibToHeaderAddr.end())
  515. HeaderAddrs[KV.first] = I->second;
  516. }
  517. }
  518. // Build the dep info map to return.
  519. MachOJITDylibDepInfoMap DIM;
  520. DIM.reserve(JDDepMap.size());
  521. for (auto &KV : JDDepMap) {
  522. auto HI = HeaderAddrs.find(KV.first);
  523. // Skip unmanaged JITDylibs.
  524. if (HI == HeaderAddrs.end())
  525. continue;
  526. auto H = HI->second;
  527. MachOJITDylibDepInfo DepInfo;
  528. for (auto &Dep : KV.second) {
  529. auto HJ = HeaderAddrs.find(Dep);
  530. if (HJ != HeaderAddrs.end())
  531. DepInfo.DepHeaders.push_back(HJ->second);
  532. }
  533. DIM.push_back(std::make_pair(H, std::move(DepInfo)));
  534. }
  535. SendResult(DIM);
  536. return;
  537. }
  538. // Otherwise issue a lookup and re-run this phase when it completes.
  539. lookupInitSymbolsAsync(
  540. [this, SendResult = std::move(SendResult), JD](Error Err) mutable {
  541. if (Err)
  542. SendResult(std::move(Err));
  543. else
  544. pushInitializersLoop(std::move(SendResult), JD);
  545. },
  546. ES, std::move(NewInitSymbols));
  547. }
  548. void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
  549. ExecutorAddr JDHeaderAddr) {
  550. JITDylibSP JD;
  551. {
  552. std::lock_guard<std::mutex> Lock(PlatformMutex);
  553. auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
  554. if (I != HeaderAddrToJITDylib.end())
  555. JD = I->second;
  556. }
  557. LLVM_DEBUG({
  558. dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
  559. if (JD)
  560. dbgs() << "pushing initializers for " << JD->getName() << "\n";
  561. else
  562. dbgs() << "No JITDylib for header address.\n";
  563. });
  564. if (!JD) {
  565. SendResult(
  566. make_error<StringError>("No JITDylib with header addr " +
  567. formatv("{0:x}", JDHeaderAddr.getValue()),
  568. inconvertibleErrorCode()));
  569. return;
  570. }
  571. pushInitializersLoop(std::move(SendResult), JD);
  572. }
  573. void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
  574. ExecutorAddr Handle, StringRef SymbolName) {
  575. LLVM_DEBUG({
  576. dbgs() << "MachOPlatform::rt_lookupSymbol(\""
  577. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  578. });
  579. JITDylib *JD = nullptr;
  580. {
  581. std::lock_guard<std::mutex> Lock(PlatformMutex);
  582. auto I = HeaderAddrToJITDylib.find(Handle);
  583. if (I != HeaderAddrToJITDylib.end())
  584. JD = I->second;
  585. }
  586. if (!JD) {
  587. LLVM_DEBUG({
  588. dbgs() << " No JITDylib for handle "
  589. << formatv("{0:x}", Handle.getValue()) << "\n";
  590. });
  591. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  592. formatv("{0:x}", Handle.getValue()),
  593. inconvertibleErrorCode()));
  594. return;
  595. }
  596. // Use functor class to work around XL build compiler issue on AIX.
  597. class RtLookupNotifyComplete {
  598. public:
  599. RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
  600. : SendResult(std::move(SendResult)) {}
  601. void operator()(Expected<SymbolMap> Result) {
  602. if (Result) {
  603. assert(Result->size() == 1 && "Unexpected result map count");
  604. SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
  605. } else {
  606. SendResult(Result.takeError());
  607. }
  608. }
  609. private:
  610. SendSymbolAddressFn SendResult;
  611. };
  612. // FIXME: Proper mangling.
  613. auto MangledName = ("_" + SymbolName).str();
  614. ES.lookup(
  615. LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
  616. SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
  617. RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
  618. }
  619. Expected<uint64_t> MachOPlatform::createPThreadKey() {
  620. if (!CreatePThreadKey.Addr)
  621. return make_error<StringError>(
  622. "Attempting to create pthread key in target, but runtime support has "
  623. "not been loaded yet",
  624. inconvertibleErrorCode());
  625. Expected<uint64_t> Result(0);
  626. if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
  627. CreatePThreadKey.Addr, Result))
  628. return std::move(Err);
  629. return Result;
  630. }
  631. void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
  632. MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
  633. jitlink::PassConfiguration &Config) {
  634. using namespace jitlink;
  635. bool InBootstrapPhase =
  636. &MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap;
  637. // If we're in the bootstrap phase then increment the active graphs.
  638. if (InBootstrapPhase) {
  639. Config.PrePrunePasses.push_back(
  640. [this](LinkGraph &G) { return bootstrapPipelineStart(G); });
  641. Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
  642. return bootstrapPipelineRecordRuntimeFunctions(G);
  643. });
  644. }
  645. // --- Handle Initializers ---
  646. if (auto InitSymbol = MR.getInitializerSymbol()) {
  647. // If the initializer symbol is the MachOHeader start symbol then just
  648. // register it and then bail out -- the header materialization unit
  649. // definitely doesn't need any other passes.
  650. if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
  651. Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) {
  652. return associateJITDylibHeaderSymbol(G, MR);
  653. });
  654. return;
  655. }
  656. // If the object contains an init symbol other than the header start symbol
  657. // then add passes to preserve, process and register the init
  658. // sections/symbols.
  659. Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
  660. if (auto Err = preserveInitSections(G, MR))
  661. return Err;
  662. return processObjCImageInfo(G, MR);
  663. });
  664. }
  665. // Insert TLV lowering at the start of the PostPrunePasses, since we want
  666. // it to run before GOT/PLT lowering.
  667. Config.PostPrunePasses.insert(
  668. Config.PostPrunePasses.begin(),
  669. [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) {
  670. return fixTLVSectionsAndEdges(G, JD);
  671. });
  672. // Add a pass to register the final addresses of any special sections in the
  673. // object with the runtime.
  674. Config.PostAllocationPasses.push_back(
  675. [this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) {
  676. return registerObjectPlatformSections(G, JD, InBootstrapPhase);
  677. });
  678. // If we're in the bootstrap phase then steal allocation actions and then
  679. // decrement the active graphs.
  680. if (InBootstrapPhase)
  681. Config.PostFixupPasses.push_back(
  682. [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
  683. }
  684. ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
  685. MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
  686. MaterializationResponsibility &MR) {
  687. std::lock_guard<std::mutex> Lock(PluginMutex);
  688. auto I = InitSymbolDeps.find(&MR);
  689. if (I != InitSymbolDeps.end()) {
  690. SyntheticSymbolDependenciesMap Result;
  691. Result[MR.getInitializerSymbol()] = std::move(I->second);
  692. InitSymbolDeps.erase(&MR);
  693. return Result;
  694. }
  695. return SyntheticSymbolDependenciesMap();
  696. }
  697. Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(
  698. jitlink::LinkGraph &G) {
  699. // Increment the active graphs count in BootstrapInfo.
  700. std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
  701. ++MP.Bootstrap.load()->ActiveGraphs;
  702. return Error::success();
  703. }
  704. Error MachOPlatform::MachOPlatformPlugin::
  705. bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
  706. // Record bootstrap function names.
  707. std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
  708. {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},
  709. {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
  710. {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
  711. {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
  712. {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
  713. {*MP.RegisterObjectPlatformSections.Name,
  714. &MP.RegisterObjectPlatformSections.Addr},
  715. {*MP.DeregisterObjectPlatformSections.Name,
  716. &MP.DeregisterObjectPlatformSections.Addr},
  717. {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}};
  718. bool RegisterMachOHeader = false;
  719. for (auto *Sym : G.defined_symbols()) {
  720. for (auto &RTSym : RuntimeSymbols) {
  721. if (Sym->hasName() && Sym->getName() == RTSym.first) {
  722. if (*RTSym.second)
  723. return make_error<StringError>(
  724. "Duplicate " + RTSym.first +
  725. " detected during MachOPlatform bootstrap",
  726. inconvertibleErrorCode());
  727. if (Sym->getName() == *MP.MachOHeaderStartSymbol)
  728. RegisterMachOHeader = true;
  729. *RTSym.second = Sym->getAddress();
  730. }
  731. }
  732. }
  733. if (RegisterMachOHeader) {
  734. // If this graph defines the macho header symbol then create the internal
  735. // mapping between it and PlatformJD.
  736. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  737. MP.JITDylibToHeaderAddr[&MP.PlatformJD] =
  738. MP.Bootstrap.load()->MachOHeaderAddr;
  739. MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =
  740. &MP.PlatformJD;
  741. }
  742. return Error::success();
  743. }
  744. Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
  745. jitlink::LinkGraph &G) {
  746. std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
  747. assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");
  748. --MP.Bootstrap.load()->ActiveGraphs;
  749. // Notify Bootstrap->CV while holding the mutex because the mutex is
  750. // also keeping Bootstrap->CV alive.
  751. if (MP.Bootstrap.load()->ActiveGraphs == 0)
  752. MP.Bootstrap.load()->CV.notify_all();
  753. return Error::success();
  754. }
  755. Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
  756. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  757. auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
  758. return Sym->getName() == *MP.MachOHeaderStartSymbol;
  759. });
  760. assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
  761. auto &JD = MR.getTargetJITDylib();
  762. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  763. auto HeaderAddr = (*I)->getAddress();
  764. MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
  765. MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
  766. // We can unconditionally add these actions to the Graph because this pass
  767. // isn't used during bootstrap.
  768. G.allocActions().push_back(
  769. {cantFail(
  770. WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(
  771. MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
  772. cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
  773. MP.DeregisterJITDylib.Addr, HeaderAddr))});
  774. return Error::success();
  775. }
  776. Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
  777. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  778. JITLinkSymbolSet InitSectionSymbols;
  779. for (auto &InitSectionName : InitSectionNames) {
  780. // Skip non-init sections.
  781. auto *InitSection = G.findSectionByName(InitSectionName);
  782. if (!InitSection)
  783. continue;
  784. // Make a pass over live symbols in the section: those blocks are already
  785. // preserved.
  786. DenseSet<jitlink::Block *> AlreadyLiveBlocks;
  787. for (auto &Sym : InitSection->symbols()) {
  788. auto &B = Sym->getBlock();
  789. if (Sym->isLive() && Sym->getOffset() == 0 &&
  790. Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
  791. InitSectionSymbols.insert(Sym);
  792. AlreadyLiveBlocks.insert(&B);
  793. }
  794. }
  795. // Add anonymous symbols to preserve any not-already-preserved blocks.
  796. for (auto *B : InitSection->blocks())
  797. if (!AlreadyLiveBlocks.count(B))
  798. InitSectionSymbols.insert(
  799. &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
  800. }
  801. if (!InitSectionSymbols.empty()) {
  802. std::lock_guard<std::mutex> Lock(PluginMutex);
  803. InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
  804. }
  805. return Error::success();
  806. }
  807. Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
  808. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  809. // If there's an ObjC imagine info then either
  810. // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
  811. // this case we name and record it.
  812. // OR
  813. // (2) We already have a recorded __objc_imageinfo for this JITDylib,
  814. // in which case we just verify it.
  815. auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
  816. if (!ObjCImageInfo)
  817. return Error::success();
  818. auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
  819. // Check that the section is not empty if present.
  820. if (ObjCImageInfoBlocks.empty())
  821. return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
  822. " section in " + G.getName(),
  823. inconvertibleErrorCode());
  824. // Check that there's only one block in the section.
  825. if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
  826. return make_error<StringError>("Multiple blocks in " +
  827. ObjCImageInfoSectionName +
  828. " section in " + G.getName(),
  829. inconvertibleErrorCode());
  830. // Check that the __objc_imageinfo section is unreferenced.
  831. // FIXME: We could optimize this check if Symbols had a ref-count.
  832. for (auto &Sec : G.sections()) {
  833. if (&Sec != ObjCImageInfo)
  834. for (auto *B : Sec.blocks())
  835. for (auto &E : B->edges())
  836. if (E.getTarget().isDefined() &&
  837. &E.getTarget().getBlock().getSection() == ObjCImageInfo)
  838. return make_error<StringError>(ObjCImageInfoSectionName +
  839. " is referenced within file " +
  840. G.getName(),
  841. inconvertibleErrorCode());
  842. }
  843. auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
  844. auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
  845. auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
  846. auto Flags =
  847. support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
  848. // Lock the mutex while we verify / update the ObjCImageInfos map.
  849. std::lock_guard<std::mutex> Lock(PluginMutex);
  850. auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
  851. if (ObjCImageInfoItr != ObjCImageInfos.end()) {
  852. // We've already registered an __objc_imageinfo section. Verify the
  853. // content of this new section matches, then delete it.
  854. if (ObjCImageInfoItr->second.first != Version)
  855. return make_error<StringError>(
  856. "ObjC version in " + G.getName() +
  857. " does not match first registered version",
  858. inconvertibleErrorCode());
  859. if (ObjCImageInfoItr->second.second != Flags)
  860. return make_error<StringError>("ObjC flags in " + G.getName() +
  861. " do not match first registered flags",
  862. inconvertibleErrorCode());
  863. // __objc_imageinfo is valid. Delete the block.
  864. for (auto *S : ObjCImageInfo->symbols())
  865. G.removeDefinedSymbol(*S);
  866. G.removeBlock(ObjCImageInfoBlock);
  867. } else {
  868. // We haven't registered an __objc_imageinfo section yet. Register and
  869. // move on. The section should already be marked no-dead-strip.
  870. ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
  871. }
  872. return Error::success();
  873. }
  874. Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
  875. jitlink::LinkGraph &G, JITDylib &JD) {
  876. // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
  877. for (auto *Sym : G.external_symbols())
  878. if (Sym->getName() == "__tlv_bootstrap") {
  879. Sym->setName("___orc_rt_macho_tlv_get_addr");
  880. break;
  881. }
  882. // Store key in __thread_vars struct fields.
  883. if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
  884. std::optional<uint64_t> Key;
  885. {
  886. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  887. auto I = MP.JITDylibToPThreadKey.find(&JD);
  888. if (I != MP.JITDylibToPThreadKey.end())
  889. Key = I->second;
  890. }
  891. if (!Key) {
  892. if (auto KeyOrErr = MP.createPThreadKey())
  893. Key = *KeyOrErr;
  894. else
  895. return KeyOrErr.takeError();
  896. }
  897. uint64_t PlatformKeyBits =
  898. support::endian::byte_swap(*Key, G.getEndianness());
  899. for (auto *B : ThreadDataSec->blocks()) {
  900. if (B->getSize() != 3 * G.getPointerSize())
  901. return make_error<StringError>("__thread_vars block at " +
  902. formatv("{0:x}", B->getAddress()) +
  903. " has unexpected size",
  904. inconvertibleErrorCode());
  905. auto NewBlockContent = G.allocateBuffer(B->getSize());
  906. llvm::copy(B->getContent(), NewBlockContent.data());
  907. memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
  908. G.getPointerSize());
  909. B->setContent(NewBlockContent);
  910. }
  911. }
  912. // Transform any TLV edges into GOT edges.
  913. for (auto *B : G.blocks())
  914. for (auto &E : B->edges())
  915. if (E.getKind() ==
  916. jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable)
  917. E.setKind(jitlink::x86_64::
  918. RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
  919. return Error::success();
  920. }
  921. std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
  922. MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
  923. jitlink::LinkGraph &G) {
  924. using namespace jitlink;
  925. UnwindSections US;
  926. // ScanSection records a section range and adds any executable blocks that
  927. // that section points to to the CodeBlocks vector.
  928. SmallVector<Block *> CodeBlocks;
  929. auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
  930. if (Sec.blocks().empty())
  931. return;
  932. SecRange = (*Sec.blocks().begin())->getRange();
  933. for (auto *B : Sec.blocks()) {
  934. auto R = B->getRange();
  935. SecRange.Start = std::min(SecRange.Start, R.Start);
  936. SecRange.End = std::max(SecRange.End, R.End);
  937. for (auto &E : B->edges()) {
  938. if (!E.getTarget().isDefined())
  939. continue;
  940. auto &TargetBlock = E.getTarget().getBlock();
  941. auto &TargetSection = TargetBlock.getSection();
  942. if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
  943. CodeBlocks.push_back(&TargetBlock);
  944. }
  945. }
  946. };
  947. if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
  948. ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
  949. if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
  950. ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
  951. // If we didn't find any pointed-to code-blocks then there's no need to
  952. // register any info.
  953. if (CodeBlocks.empty())
  954. return std::nullopt;
  955. // We have info to register. Sort the code blocks into address order and
  956. // build a list of contiguous address ranges covering them all.
  957. llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
  958. return LHS->getAddress() < RHS->getAddress();
  959. });
  960. for (auto *B : CodeBlocks) {
  961. if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
  962. US.CodeRanges.push_back(B->getRange());
  963. else
  964. US.CodeRanges.back().End = B->getRange().End;
  965. }
  966. LLVM_DEBUG({
  967. dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
  968. << " DWARF: ";
  969. if (US.DwarfSection.Start)
  970. dbgs() << US.DwarfSection << "\n";
  971. else
  972. dbgs() << "none\n";
  973. dbgs() << " Compact-unwind: ";
  974. if (US.CompactUnwindSection.Start)
  975. dbgs() << US.CompactUnwindSection << "\n";
  976. else
  977. dbgs() << "none\n"
  978. << "for code ranges:\n";
  979. for (auto &CR : US.CodeRanges)
  980. dbgs() << " " << CR << "\n";
  981. if (US.CodeRanges.size() >= G.sections_size())
  982. dbgs() << "WARNING: High number of discontiguous code ranges! "
  983. "Padding may be interfering with coalescing.\n";
  984. });
  985. return US;
  986. }
  987. Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
  988. jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) {
  989. // Get a pointer to the thread data section if there is one. It will be used
  990. // below.
  991. jitlink::Section *ThreadDataSection =
  992. G.findSectionByName(ThreadDataSectionName);
  993. // Handle thread BSS section if there is one.
  994. if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
  995. // If there's already a thread data section in this graph then merge the
  996. // thread BSS section content into it, otherwise just treat the thread
  997. // BSS section as the thread data section.
  998. if (ThreadDataSection)
  999. G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
  1000. else
  1001. ThreadDataSection = ThreadBSSSection;
  1002. }
  1003. SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;
  1004. // Collect data sections to register.
  1005. StringRef DataSections[] = {DataDataSectionName, DataCommonSectionName,
  1006. EHFrameSectionName};
  1007. for (auto &SecName : DataSections) {
  1008. if (auto *Sec = G.findSectionByName(SecName)) {
  1009. jitlink::SectionRange R(*Sec);
  1010. if (!R.empty())
  1011. MachOPlatformSecs.push_back({SecName, R.getRange()});
  1012. }
  1013. }
  1014. // Having merged thread BSS (if present) and thread data (if present),
  1015. // record the resulting section range.
  1016. if (ThreadDataSection) {
  1017. jitlink::SectionRange R(*ThreadDataSection);
  1018. if (!R.empty())
  1019. MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
  1020. }
  1021. // If any platform sections were found then add an allocation action to call
  1022. // the registration function.
  1023. StringRef PlatformSections[] = {
  1024. ModInitFuncSectionName, ObjCClassListSectionName,
  1025. ObjCImageInfoSectionName, ObjCSelRefsSectionName,
  1026. Swift5ProtoSectionName, Swift5ProtosSectionName,
  1027. Swift5TypesSectionName,
  1028. };
  1029. for (auto &SecName : PlatformSections) {
  1030. auto *Sec = G.findSectionByName(SecName);
  1031. if (!Sec)
  1032. continue;
  1033. jitlink::SectionRange R(*Sec);
  1034. if (R.empty())
  1035. continue;
  1036. MachOPlatformSecs.push_back({SecName, R.getRange()});
  1037. }
  1038. std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,
  1039. ExecutorAddrRange>>
  1040. UnwindInfo;
  1041. if (auto UI = findUnwindSectionInfo(G))
  1042. UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
  1043. UI->CompactUnwindSection);
  1044. if (!MachOPlatformSecs.empty() || UnwindInfo) {
  1045. ExecutorAddr HeaderAddr;
  1046. {
  1047. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  1048. auto I = MP.JITDylibToHeaderAddr.find(&JD);
  1049. assert(I != MP.JITDylibToHeaderAddr.end() &&
  1050. "Missing header for JITDylib");
  1051. HeaderAddr = I->second;
  1052. }
  1053. // Dump the scraped inits.
  1054. LLVM_DEBUG({
  1055. dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
  1056. for (auto &KV : MachOPlatformSecs)
  1057. dbgs() << " " << KV.first << ": " << KV.second << "\n";
  1058. });
  1059. using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
  1060. SPSExecutorAddr,
  1061. SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>,
  1062. SPSExecutorAddrRange, SPSExecutorAddrRange>>,
  1063. SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
  1064. shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)
  1065. ? G.allocActions()
  1066. : MP.Bootstrap.load()->DeferredAAs;
  1067. allocActions.push_back(
  1068. {cantFail(
  1069. WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
  1070. MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
  1071. MachOPlatformSecs)),
  1072. cantFail(
  1073. WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
  1074. MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
  1075. UnwindInfo, MachOPlatformSecs))});
  1076. }
  1077. return Error::success();
  1078. }
  1079. } // End namespace orc.
  1080. } // End namespace llvm.