COFFPlatform.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. //===------- COFFPlatform.cpp - Utilities for executing COFF 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/COFFPlatform.h"
  9. #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
  10. #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
  11. #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
  12. #include "llvm/Object/COFF.h"
  13. #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
  14. #include "llvm/ExecutionEngine/JITLink/x86_64.h"
  15. #define DEBUG_TYPE "orc"
  16. using namespace llvm;
  17. using namespace llvm::orc;
  18. using namespace llvm::orc::shared;
  19. namespace llvm {
  20. namespace orc {
  21. namespace shared {
  22. using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
  23. using SPSCOFFJITDylibDepInfoMap =
  24. SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
  25. using SPSCOFFObjectSectionsMap =
  26. SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
  27. using SPSCOFFRegisterObjectSectionsArgs =
  28. SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
  29. using SPSCOFFDeregisterObjectSectionsArgs =
  30. SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
  31. } // namespace shared
  32. } // namespace orc
  33. } // namespace llvm
  34. namespace {
  35. class COFFHeaderMaterializationUnit : public MaterializationUnit {
  36. public:
  37. COFFHeaderMaterializationUnit(COFFPlatform &CP,
  38. const SymbolStringPtr &HeaderStartSymbol)
  39. : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
  40. CP(CP) {}
  41. StringRef getName() const override { return "COFFHeaderMU"; }
  42. void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
  43. unsigned PointerSize;
  44. support::endianness Endianness;
  45. const auto &TT =
  46. CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
  47. switch (TT.getArch()) {
  48. case Triple::x86_64:
  49. PointerSize = 8;
  50. Endianness = support::endianness::little;
  51. break;
  52. default:
  53. llvm_unreachable("Unrecognized architecture");
  54. }
  55. auto G = std::make_unique<jitlink::LinkGraph>(
  56. "<COFFHeaderMU>", TT, PointerSize, Endianness,
  57. jitlink::getGenericEdgeKindName);
  58. auto &HeaderSection = G->createSection("__header", MemProt::Read);
  59. auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
  60. // Init symbol is __ImageBase symbol.
  61. auto &ImageBaseSymbol = G->addDefinedSymbol(
  62. HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
  63. jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
  64. addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
  65. CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  66. }
  67. void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
  68. private:
  69. struct HeaderSymbol {
  70. const char *Name;
  71. uint64_t Offset;
  72. };
  73. struct NTHeader {
  74. support::ulittle32_t PEMagic;
  75. object::coff_file_header FileHeader;
  76. struct PEHeader {
  77. object::pe32plus_header Header;
  78. object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
  79. } OptionalHeader;
  80. };
  81. struct HeaderBlockContent {
  82. object::dos_header DOSHeader;
  83. COFFHeaderMaterializationUnit::NTHeader NTHeader;
  84. };
  85. static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
  86. jitlink::Section &HeaderSection) {
  87. HeaderBlockContent Hdr = {};
  88. // Set up magic
  89. Hdr.DOSHeader.Magic[0] = 'M';
  90. Hdr.DOSHeader.Magic[1] = 'Z';
  91. Hdr.DOSHeader.AddressOfNewExeHeader =
  92. offsetof(HeaderBlockContent, NTHeader);
  93. uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
  94. Hdr.NTHeader.PEMagic = PEMagic;
  95. Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
  96. switch (G.getTargetTriple().getArch()) {
  97. case Triple::x86_64:
  98. Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
  99. break;
  100. default:
  101. llvm_unreachable("Unrecognized architecture");
  102. }
  103. auto HeaderContent = G.allocateString(
  104. StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
  105. return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
  106. 0);
  107. }
  108. static void addImageBaseRelocationEdge(jitlink::Block &B,
  109. jitlink::Symbol &ImageBase) {
  110. auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
  111. offsetof(NTHeader, OptionalHeader) +
  112. offsetof(object::pe32plus_header, ImageBase);
  113. B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
  114. }
  115. static MaterializationUnit::Interface
  116. createHeaderInterface(COFFPlatform &MOP,
  117. const SymbolStringPtr &HeaderStartSymbol) {
  118. SymbolFlagsMap HeaderSymbolFlags;
  119. HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
  120. return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
  121. HeaderStartSymbol);
  122. }
  123. COFFPlatform &CP;
  124. };
  125. } // end anonymous namespace
  126. namespace llvm {
  127. namespace orc {
  128. Expected<std::unique_ptr<COFFPlatform>>
  129. COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  130. JITDylib &PlatformJD, const char *OrcRuntimePath,
  131. LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
  132. const char *VCRuntimePath,
  133. std::optional<SymbolAliasMap> RuntimeAliases) {
  134. auto &EPC = ES.getExecutorProcessControl();
  135. // If the target is not supported then bail out immediately.
  136. if (!supportedTarget(EPC.getTargetTriple()))
  137. return make_error<StringError>("Unsupported COFFPlatform triple: " +
  138. EPC.getTargetTriple().str(),
  139. inconvertibleErrorCode());
  140. // Create default aliases if the caller didn't supply any.
  141. if (!RuntimeAliases)
  142. RuntimeAliases = standardPlatformAliases(ES);
  143. // Define the aliases.
  144. if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
  145. return std::move(Err);
  146. auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
  147. // Add JIT-dispatch function support symbols.
  148. if (auto Err = HostFuncJD.define(absoluteSymbols(
  149. {{ES.intern("__orc_rt_jit_dispatch"),
  150. {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
  151. JITSymbolFlags::Exported}},
  152. {ES.intern("__orc_rt_jit_dispatch_ctx"),
  153. {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
  154. JITSymbolFlags::Exported}}})))
  155. return std::move(Err);
  156. PlatformJD.addToLinkOrder(HostFuncJD);
  157. // Create the instance.
  158. Error Err = Error::success();
  159. auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
  160. ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
  161. std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
  162. if (Err)
  163. return std::move(Err);
  164. return std::move(P);
  165. }
  166. Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
  167. auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
  168. if (!PerJDObj)
  169. return PerJDObj.takeError();
  170. if (!*PerJDObj)
  171. return make_error<StringError>("Could not find per jd object file",
  172. inconvertibleErrorCode());
  173. auto Buffer = (*PerJDObj)->getAsBinary();
  174. if (!Buffer)
  175. return Buffer.takeError();
  176. return (*Buffer)->getMemoryBufferRef();
  177. }
  178. static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
  179. ArrayRef<std::pair<const char *, const char *>> AL) {
  180. for (auto &KV : AL) {
  181. auto AliasName = ES.intern(KV.first);
  182. assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
  183. Aliases[std::move(AliasName)] = {ES.intern(KV.second),
  184. JITSymbolFlags::Exported};
  185. }
  186. }
  187. Error COFFPlatform::setupJITDylib(JITDylib &JD) {
  188. if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
  189. *this, COFFHeaderStartSymbol)))
  190. return Err;
  191. if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
  192. return Err;
  193. // Define the CXX aliases.
  194. SymbolAliasMap CXXAliases;
  195. addAliases(ES, CXXAliases, requiredCXXAliases());
  196. if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
  197. return Err;
  198. auto PerJDObj = getPerJDObjectFile();
  199. if (!PerJDObj)
  200. return PerJDObj.takeError();
  201. auto I = getObjectFileInterface(ES, *PerJDObj);
  202. if (!I)
  203. return I.takeError();
  204. if (auto Err = ObjLinkingLayer.add(
  205. JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
  206. return Err;
  207. if (!Bootstrapping) {
  208. auto ImportedLibs = StaticVCRuntime
  209. ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
  210. : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
  211. if (!ImportedLibs)
  212. return ImportedLibs.takeError();
  213. for (auto &Lib : *ImportedLibs)
  214. if (auto Err = LoadDynLibrary(JD, Lib))
  215. return Err;
  216. if (StaticVCRuntime)
  217. if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
  218. return Err;
  219. }
  220. JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
  221. return Error::success();
  222. }
  223. Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
  224. std::lock_guard<std::mutex> Lock(PlatformMutex);
  225. auto I = JITDylibToHeaderAddr.find(&JD);
  226. if (I != JITDylibToHeaderAddr.end()) {
  227. assert(HeaderAddrToJITDylib.count(I->second) &&
  228. "HeaderAddrToJITDylib missing entry");
  229. HeaderAddrToJITDylib.erase(I->second);
  230. JITDylibToHeaderAddr.erase(I);
  231. }
  232. return Error::success();
  233. }
  234. Error COFFPlatform::notifyAdding(ResourceTracker &RT,
  235. const MaterializationUnit &MU) {
  236. auto &JD = RT.getJITDylib();
  237. const auto &InitSym = MU.getInitializerSymbol();
  238. if (!InitSym)
  239. return Error::success();
  240. RegisteredInitSymbols[&JD].add(InitSym,
  241. SymbolLookupFlags::WeaklyReferencedSymbol);
  242. LLVM_DEBUG({
  243. dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
  244. << MU.getName() << "\n";
  245. });
  246. return Error::success();
  247. }
  248. Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
  249. llvm_unreachable("Not supported yet");
  250. }
  251. SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
  252. SymbolAliasMap Aliases;
  253. addAliases(ES, Aliases, standardRuntimeUtilityAliases());
  254. return Aliases;
  255. }
  256. ArrayRef<std::pair<const char *, const char *>>
  257. COFFPlatform::requiredCXXAliases() {
  258. static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
  259. {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
  260. {"_onexit", "__orc_rt_coff_onexit_per_jd"},
  261. {"atexit", "__orc_rt_coff_atexit_per_jd"}};
  262. return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
  263. }
  264. ArrayRef<std::pair<const char *, const char *>>
  265. COFFPlatform::standardRuntimeUtilityAliases() {
  266. static const std::pair<const char *, const char *>
  267. StandardRuntimeUtilityAliases[] = {
  268. {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
  269. {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
  270. {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
  271. {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
  272. {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
  273. {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
  274. return ArrayRef<std::pair<const char *, const char *>>(
  275. StandardRuntimeUtilityAliases);
  276. }
  277. bool COFFPlatform::supportedTarget(const Triple &TT) {
  278. switch (TT.getArch()) {
  279. case Triple::x86_64:
  280. return true;
  281. default:
  282. return false;
  283. }
  284. }
  285. COFFPlatform::COFFPlatform(ExecutionSession &ES,
  286. ObjectLinkingLayer &ObjLinkingLayer,
  287. JITDylib &PlatformJD, const char *OrcRuntimePath,
  288. LoadDynamicLibrary LoadDynLibrary,
  289. bool StaticVCRuntime, const char *VCRuntimePath,
  290. Error &Err)
  291. : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
  292. LoadDynLibrary(std::move(LoadDynLibrary)),
  293. StaticVCRuntime(StaticVCRuntime),
  294. COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
  295. ErrorAsOutParameter _(&Err);
  296. // Create a generator for the ORC runtime archive.
  297. auto OrcRuntimeArchiveGenerator =
  298. StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
  299. if (!OrcRuntimeArchiveGenerator) {
  300. Err = OrcRuntimeArchiveGenerator.takeError();
  301. return;
  302. }
  303. auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
  304. if (!ArchiveBuffer) {
  305. Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
  306. return;
  307. }
  308. OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
  309. OrcRuntimeArchive =
  310. std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
  311. if (Err)
  312. return;
  313. Bootstrapping.store(true);
  314. ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
  315. // Load vc runtime
  316. auto VCRT =
  317. COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
  318. if (!VCRT) {
  319. Err = VCRT.takeError();
  320. return;
  321. }
  322. VCRuntimeBootstrap = std::move(*VCRT);
  323. for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
  324. DylibsToPreload.insert(Lib);
  325. auto ImportedLibs =
  326. StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
  327. : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
  328. if (!ImportedLibs) {
  329. Err = ImportedLibs.takeError();
  330. return;
  331. }
  332. for (auto &Lib : *ImportedLibs)
  333. DylibsToPreload.insert(Lib);
  334. PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
  335. // PlatformJD hasn't been set up by the platform yet (since we're creating
  336. // the platform now), so set it up.
  337. if (auto E2 = setupJITDylib(PlatformJD)) {
  338. Err = std::move(E2);
  339. return;
  340. }
  341. for (auto& Lib : DylibsToPreload)
  342. if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
  343. Err = std::move(E2);
  344. return;
  345. }
  346. if (StaticVCRuntime)
  347. if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
  348. Err = std::move(E2);
  349. return;
  350. }
  351. // Associate wrapper function tags with JIT-side function implementations.
  352. if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
  353. Err = std::move(E2);
  354. return;
  355. }
  356. // Lookup addresses of runtime functions callable by the platform,
  357. // call the platform bootstrap function to initialize the platform-state
  358. // object in the executor.
  359. if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
  360. Err = std::move(E2);
  361. return;
  362. }
  363. Bootstrapping.store(false);
  364. JDBootstrapStates.clear();
  365. }
  366. Expected<COFFPlatform::JITDylibDepMap>
  367. COFFPlatform::buildJDDepMap(JITDylib &JD) {
  368. return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
  369. JITDylibDepMap JDDepMap;
  370. SmallVector<JITDylib *, 16> Worklist({&JD});
  371. while (!Worklist.empty()) {
  372. auto CurJD = Worklist.back();
  373. Worklist.pop_back();
  374. auto &DM = JDDepMap[CurJD];
  375. CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
  376. DM.reserve(O.size());
  377. for (auto &KV : O) {
  378. if (KV.first == CurJD)
  379. continue;
  380. {
  381. // Bare jitdylibs not known to the platform
  382. std::lock_guard<std::mutex> Lock(PlatformMutex);
  383. if (!JITDylibToHeaderAddr.count(KV.first)) {
  384. LLVM_DEBUG({
  385. dbgs() << "JITDylib unregistered to COFFPlatform detected in "
  386. "LinkOrder: "
  387. << CurJD->getName() << "\n";
  388. });
  389. continue;
  390. }
  391. }
  392. DM.push_back(KV.first);
  393. // Push unvisited entry.
  394. if (!JDDepMap.count(KV.first)) {
  395. Worklist.push_back(KV.first);
  396. JDDepMap[KV.first] = {};
  397. }
  398. }
  399. });
  400. }
  401. return std::move(JDDepMap);
  402. });
  403. }
  404. void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
  405. JITDylibSP JD,
  406. JITDylibDepMap &JDDepMap) {
  407. SmallVector<JITDylib *, 16> Worklist({JD.get()});
  408. DenseSet<JITDylib *> Visited({JD.get()});
  409. DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
  410. ES.runSessionLocked([&]() {
  411. while (!Worklist.empty()) {
  412. auto CurJD = Worklist.back();
  413. Worklist.pop_back();
  414. auto RISItr = RegisteredInitSymbols.find(CurJD);
  415. if (RISItr != RegisteredInitSymbols.end()) {
  416. NewInitSymbols[CurJD] = std::move(RISItr->second);
  417. RegisteredInitSymbols.erase(RISItr);
  418. }
  419. for (auto *DepJD : JDDepMap[CurJD])
  420. if (!Visited.count(DepJD)) {
  421. Worklist.push_back(DepJD);
  422. Visited.insert(DepJD);
  423. }
  424. }
  425. });
  426. // If there are no further init symbols to look up then send the link order
  427. // (as a list of header addresses) to the caller.
  428. if (NewInitSymbols.empty()) {
  429. // Build the dep info map to return.
  430. COFFJITDylibDepInfoMap DIM;
  431. DIM.reserve(JDDepMap.size());
  432. for (auto &KV : JDDepMap) {
  433. std::lock_guard<std::mutex> Lock(PlatformMutex);
  434. COFFJITDylibDepInfo DepInfo;
  435. DepInfo.reserve(KV.second.size());
  436. for (auto &Dep : KV.second) {
  437. DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
  438. }
  439. auto H = JITDylibToHeaderAddr[KV.first];
  440. DIM.push_back(std::make_pair(H, std::move(DepInfo)));
  441. }
  442. SendResult(DIM);
  443. return;
  444. }
  445. // Otherwise issue a lookup and re-run this phase when it completes.
  446. lookupInitSymbolsAsync(
  447. [this, SendResult = std::move(SendResult), &JD,
  448. JDDepMap = std::move(JDDepMap)](Error Err) mutable {
  449. if (Err)
  450. SendResult(std::move(Err));
  451. else
  452. pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
  453. },
  454. ES, std::move(NewInitSymbols));
  455. }
  456. void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
  457. ExecutorAddr JDHeaderAddr) {
  458. JITDylibSP JD;
  459. {
  460. std::lock_guard<std::mutex> Lock(PlatformMutex);
  461. auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
  462. if (I != HeaderAddrToJITDylib.end())
  463. JD = I->second;
  464. }
  465. LLVM_DEBUG({
  466. dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
  467. if (JD)
  468. dbgs() << "pushing initializers for " << JD->getName() << "\n";
  469. else
  470. dbgs() << "No JITDylib for header address.\n";
  471. });
  472. if (!JD) {
  473. SendResult(
  474. make_error<StringError>("No JITDylib with header addr " +
  475. formatv("{0:x}", JDHeaderAddr.getValue()),
  476. inconvertibleErrorCode()));
  477. return;
  478. }
  479. auto JDDepMap = buildJDDepMap(*JD);
  480. if (!JDDepMap) {
  481. SendResult(JDDepMap.takeError());
  482. return;
  483. }
  484. pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
  485. }
  486. void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
  487. ExecutorAddr Handle, StringRef SymbolName) {
  488. LLVM_DEBUG({
  489. dbgs() << "COFFPlatform::rt_lookupSymbol(\""
  490. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  491. });
  492. JITDylib *JD = nullptr;
  493. {
  494. std::lock_guard<std::mutex> Lock(PlatformMutex);
  495. auto I = HeaderAddrToJITDylib.find(Handle);
  496. if (I != HeaderAddrToJITDylib.end())
  497. JD = I->second;
  498. }
  499. if (!JD) {
  500. LLVM_DEBUG({
  501. dbgs() << " No JITDylib for handle "
  502. << formatv("{0:x}", Handle.getValue()) << "\n";
  503. });
  504. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  505. formatv("{0:x}", Handle.getValue()),
  506. inconvertibleErrorCode()));
  507. return;
  508. }
  509. // Use functor class to work around XL build compiler issue on AIX.
  510. class RtLookupNotifyComplete {
  511. public:
  512. RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
  513. : SendResult(std::move(SendResult)) {}
  514. void operator()(Expected<SymbolMap> Result) {
  515. if (Result) {
  516. assert(Result->size() == 1 && "Unexpected result map count");
  517. SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
  518. } else {
  519. SendResult(Result.takeError());
  520. }
  521. }
  522. private:
  523. SendSymbolAddressFn SendResult;
  524. };
  525. ES.lookup(
  526. LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
  527. SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
  528. RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
  529. }
  530. Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
  531. ExecutionSession::JITDispatchHandlerAssociationMap WFs;
  532. using LookupSymbolSPSSig =
  533. SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
  534. WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
  535. ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
  536. &COFFPlatform::rt_lookupSymbol);
  537. using PushInitializersSPSSig =
  538. SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
  539. WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
  540. ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
  541. this, &COFFPlatform::rt_pushInitializers);
  542. return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
  543. }
  544. Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
  545. llvm::sort(BState.Initializers);
  546. if (auto Err =
  547. runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
  548. return Err;
  549. if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
  550. return Err;
  551. if (auto Err =
  552. runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
  553. return Err;
  554. return Error::success();
  555. }
  556. Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
  557. StringRef Start,
  558. StringRef End) {
  559. for (auto &Initializer : BState.Initializers)
  560. if (Initializer.first >= Start && Initializer.first <= End &&
  561. Initializer.second) {
  562. auto Res =
  563. ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
  564. if (!Res)
  565. return Res.takeError();
  566. }
  567. return Error::success();
  568. }
  569. Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
  570. // Lookup of runtime symbols causes the collection of initializers if
  571. // it's static linking setting.
  572. if (auto Err = lookupAndRecordAddrs(
  573. ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
  574. {
  575. {ES.intern("__orc_rt_coff_platform_bootstrap"),
  576. &orc_rt_coff_platform_bootstrap},
  577. {ES.intern("__orc_rt_coff_platform_shutdown"),
  578. &orc_rt_coff_platform_shutdown},
  579. {ES.intern("__orc_rt_coff_register_jitdylib"),
  580. &orc_rt_coff_register_jitdylib},
  581. {ES.intern("__orc_rt_coff_deregister_jitdylib"),
  582. &orc_rt_coff_deregister_jitdylib},
  583. {ES.intern("__orc_rt_coff_register_object_sections"),
  584. &orc_rt_coff_register_object_sections},
  585. {ES.intern("__orc_rt_coff_deregister_object_sections"),
  586. &orc_rt_coff_deregister_object_sections},
  587. }))
  588. return Err;
  589. // Call bootstrap functions
  590. if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
  591. return Err;
  592. // Do the pending jitdylib registration actions that we couldn't do
  593. // because orc runtime was not linked fully.
  594. for (auto KV : JDBootstrapStates) {
  595. auto &JDBState = KV.second;
  596. if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
  597. orc_rt_coff_register_jitdylib, JDBState.JDName,
  598. JDBState.HeaderAddr))
  599. return Err;
  600. for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
  601. if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
  602. SPSCOFFObjectSectionsMap, bool)>(
  603. orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
  604. ObjSectionMap, false))
  605. return Err;
  606. }
  607. // Run static initializers collected in bootstrap stage.
  608. for (auto KV : JDBootstrapStates) {
  609. auto &JDBState = KV.second;
  610. if (auto Err = runBootstrapInitializers(JDBState))
  611. return Err;
  612. }
  613. return Error::success();
  614. }
  615. Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
  616. StringRef SymbolName) {
  617. ExecutorAddr jit_function;
  618. auto AfterCLookupErr = lookupAndRecordAddrs(
  619. ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
  620. {{ES.intern(SymbolName), &jit_function}});
  621. if (!AfterCLookupErr) {
  622. auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
  623. if (!Res)
  624. return Res.takeError();
  625. return Error::success();
  626. }
  627. if (!AfterCLookupErr.isA<SymbolsNotFound>())
  628. return AfterCLookupErr;
  629. consumeError(std::move(AfterCLookupErr));
  630. return Error::success();
  631. }
  632. void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
  633. MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
  634. jitlink::PassConfiguration &Config) {
  635. bool IsBootstrapping = CP.Bootstrapping.load();
  636. if (auto InitSymbol = MR.getInitializerSymbol()) {
  637. if (InitSymbol == CP.COFFHeaderStartSymbol) {
  638. Config.PostAllocationPasses.push_back(
  639. [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
  640. return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
  641. });
  642. return;
  643. }
  644. Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
  645. return preserveInitializerSections(G, MR);
  646. });
  647. }
  648. if (!IsBootstrapping)
  649. Config.PostFixupPasses.push_back(
  650. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  651. return registerObjectPlatformSections(G, JD);
  652. });
  653. else
  654. Config.PostFixupPasses.push_back(
  655. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  656. return registerObjectPlatformSectionsInBootstrap(G, JD);
  657. });
  658. }
  659. ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
  660. COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
  661. MaterializationResponsibility &MR) {
  662. std::lock_guard<std::mutex> Lock(PluginMutex);
  663. auto I = InitSymbolDeps.find(&MR);
  664. if (I != InitSymbolDeps.end()) {
  665. SyntheticSymbolDependenciesMap Result;
  666. Result[MR.getInitializerSymbol()] = std::move(I->second);
  667. InitSymbolDeps.erase(&MR);
  668. return Result;
  669. }
  670. return SyntheticSymbolDependenciesMap();
  671. }
  672. Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
  673. jitlink::LinkGraph &G, MaterializationResponsibility &MR,
  674. bool IsBootstraping) {
  675. auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
  676. return Sym->getName() == *CP.COFFHeaderStartSymbol;
  677. });
  678. assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
  679. auto &JD = MR.getTargetJITDylib();
  680. std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
  681. auto HeaderAddr = (*I)->getAddress();
  682. CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
  683. CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
  684. if (!IsBootstraping) {
  685. G.allocActions().push_back(
  686. {cantFail(WrapperFunctionCall::Create<
  687. SPSArgList<SPSString, SPSExecutorAddr>>(
  688. CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
  689. cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
  690. CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
  691. } else {
  692. G.allocActions().push_back(
  693. {{},
  694. cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
  695. CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
  696. JDBootstrapState BState;
  697. BState.JD = &JD;
  698. BState.JDName = JD.getName();
  699. BState.HeaderAddr = HeaderAddr;
  700. CP.JDBootstrapStates.emplace(&JD, BState);
  701. }
  702. return Error::success();
  703. }
  704. Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
  705. jitlink::LinkGraph &G, JITDylib &JD) {
  706. COFFObjectSectionsMap ObjSecs;
  707. auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
  708. assert(HeaderAddr && "Must be registered jitdylib");
  709. for (auto &S : G.sections()) {
  710. jitlink::SectionRange Range(S);
  711. if (Range.getSize())
  712. ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
  713. }
  714. G.allocActions().push_back(
  715. {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
  716. CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
  717. cantFail(
  718. WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
  719. CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
  720. ObjSecs))});
  721. return Error::success();
  722. }
  723. Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
  724. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  725. JITLinkSymbolSet InitSectionSymbols;
  726. for (auto &Sec : G.sections())
  727. if (COFFPlatform::isInitializerSection(Sec.getName()))
  728. for (auto *B : Sec.blocks())
  729. if (!B->edges_empty())
  730. InitSectionSymbols.insert(
  731. &G.addAnonymousSymbol(*B, 0, 0, false, true));
  732. std::lock_guard<std::mutex> Lock(PluginMutex);
  733. InitSymbolDeps[&MR] = InitSectionSymbols;
  734. return Error::success();
  735. }
  736. Error COFFPlatform::COFFPlatformPlugin::
  737. registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
  738. JITDylib &JD) {
  739. std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
  740. auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
  741. COFFObjectSectionsMap ObjSecs;
  742. for (auto &S : G.sections()) {
  743. jitlink::SectionRange Range(S);
  744. if (Range.getSize())
  745. ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
  746. }
  747. G.allocActions().push_back(
  748. {{},
  749. cantFail(
  750. WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
  751. CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
  752. ObjSecs))});
  753. auto &BState = CP.JDBootstrapStates[&JD];
  754. BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
  755. // Collect static initializers
  756. for (auto &S : G.sections())
  757. if (COFFPlatform::isInitializerSection(S.getName()))
  758. for (auto *B : S.blocks()) {
  759. if (B->edges_empty())
  760. continue;
  761. for (auto &E : B->edges())
  762. BState.Initializers.push_back(std::make_pair(
  763. S.getName().str(),
  764. ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
  765. }
  766. return Error::success();
  767. }
  768. } // End namespace orc.
  769. } // End namespace llvm.