ELFNixPlatform.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. //===------ ELFNixPlatform.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/ELFNixPlatform.h"
  9. #include "llvm/BinaryFormat/ELF.h"
  10. #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
  11. #include "llvm/ExecutionEngine/JITLink/x86_64.h"
  12. #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
  13. #include "llvm/ExecutionEngine/Orc/ExecutionUtils.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 DSOHandleMaterializationUnit : public MaterializationUnit {
  22. public:
  23. DSOHandleMaterializationUnit(ELFNixPlatform &ENP,
  24. const SymbolStringPtr &DSOHandleSymbol)
  25. : MaterializationUnit(
  26. createDSOHandleSectionInterface(ENP, DSOHandleSymbol)),
  27. ENP(ENP) {}
  28. StringRef getName() const override { return "DSOHandleMU"; }
  29. void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
  30. unsigned PointerSize;
  31. support::endianness Endianness;
  32. jitlink::Edge::Kind EdgeKind;
  33. const auto &TT =
  34. ENP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
  35. switch (TT.getArch()) {
  36. case Triple::x86_64:
  37. PointerSize = 8;
  38. Endianness = support::endianness::little;
  39. EdgeKind = jitlink::x86_64::Pointer64;
  40. break;
  41. default:
  42. llvm_unreachable("Unrecognized architecture");
  43. }
  44. // void *__dso_handle = &__dso_handle;
  45. auto G = std::make_unique<jitlink::LinkGraph>(
  46. "<DSOHandleMU>", TT, PointerSize, Endianness,
  47. jitlink::getGenericEdgeKindName);
  48. auto &DSOHandleSection =
  49. G->createSection(".data.__dso_handle", jitlink::MemProt::Read);
  50. auto &DSOHandleBlock = G->createContentBlock(
  51. DSOHandleSection, getDSOHandleContent(PointerSize), orc::ExecutorAddr(),
  52. 8, 0);
  53. auto &DSOHandleSymbol = G->addDefinedSymbol(
  54. DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(),
  55. jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
  56. DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0);
  57. ENP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  58. }
  59. void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
  60. private:
  61. static MaterializationUnit::Interface
  62. createDSOHandleSectionInterface(ELFNixPlatform &ENP,
  63. const SymbolStringPtr &DSOHandleSymbol) {
  64. SymbolFlagsMap SymbolFlags;
  65. SymbolFlags[DSOHandleSymbol] = JITSymbolFlags::Exported;
  66. return MaterializationUnit::Interface(std::move(SymbolFlags),
  67. DSOHandleSymbol);
  68. }
  69. ArrayRef<char> getDSOHandleContent(size_t PointerSize) {
  70. static const char Content[8] = {0};
  71. assert(PointerSize <= sizeof Content);
  72. return {Content, PointerSize};
  73. }
  74. ELFNixPlatform &ENP;
  75. };
  76. StringRef EHFrameSectionName = ".eh_frame";
  77. StringRef InitArrayFuncSectionName = ".init_array";
  78. StringRef ThreadBSSSectionName = ".tbss";
  79. StringRef ThreadDataSectionName = ".tdata";
  80. StringRef InitSectionNames[] = {InitArrayFuncSectionName};
  81. } // end anonymous namespace
  82. namespace llvm {
  83. namespace orc {
  84. Expected<std::unique_ptr<ELFNixPlatform>>
  85. ELFNixPlatform::Create(ExecutionSession &ES,
  86. ObjectLinkingLayer &ObjLinkingLayer,
  87. JITDylib &PlatformJD, const char *OrcRuntimePath,
  88. Optional<SymbolAliasMap> RuntimeAliases) {
  89. auto &EPC = ES.getExecutorProcessControl();
  90. // If the target is not supported then bail out immediately.
  91. if (!supportedTarget(EPC.getTargetTriple()))
  92. return make_error<StringError>("Unsupported ELFNixPlatform triple: " +
  93. EPC.getTargetTriple().str(),
  94. inconvertibleErrorCode());
  95. // Create default aliases if the caller didn't supply any.
  96. if (!RuntimeAliases)
  97. RuntimeAliases = standardPlatformAliases(ES);
  98. // Define the aliases.
  99. if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
  100. return std::move(Err);
  101. // Add JIT-dispatch function support symbols.
  102. if (auto Err = PlatformJD.define(absoluteSymbols(
  103. {{ES.intern("__orc_rt_jit_dispatch"),
  104. {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
  105. JITSymbolFlags::Exported}},
  106. {ES.intern("__orc_rt_jit_dispatch_ctx"),
  107. {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
  108. JITSymbolFlags::Exported}}})))
  109. return std::move(Err);
  110. // Create a generator for the ORC runtime archive.
  111. auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
  112. ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
  113. if (!OrcRuntimeArchiveGenerator)
  114. return OrcRuntimeArchiveGenerator.takeError();
  115. // Create the instance.
  116. Error Err = Error::success();
  117. auto P = std::unique_ptr<ELFNixPlatform>(
  118. new ELFNixPlatform(ES, ObjLinkingLayer, PlatformJD,
  119. std::move(*OrcRuntimeArchiveGenerator), Err));
  120. if (Err)
  121. return std::move(Err);
  122. return std::move(P);
  123. }
  124. Error ELFNixPlatform::setupJITDylib(JITDylib &JD) {
  125. return JD.define(
  126. std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol));
  127. }
  128. Error ELFNixPlatform::teardownJITDylib(JITDylib &JD) {
  129. return Error::success();
  130. }
  131. Error ELFNixPlatform::notifyAdding(ResourceTracker &RT,
  132. const MaterializationUnit &MU) {
  133. auto &JD = RT.getJITDylib();
  134. const auto &InitSym = MU.getInitializerSymbol();
  135. if (!InitSym)
  136. return Error::success();
  137. RegisteredInitSymbols[&JD].add(InitSym,
  138. SymbolLookupFlags::WeaklyReferencedSymbol);
  139. LLVM_DEBUG({
  140. dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym
  141. << " for MU " << MU.getName() << "\n";
  142. });
  143. return Error::success();
  144. }
  145. Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) {
  146. llvm_unreachable("Not supported yet");
  147. }
  148. static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
  149. ArrayRef<std::pair<const char *, const char *>> AL) {
  150. for (auto &KV : AL) {
  151. auto AliasName = ES.intern(KV.first);
  152. assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
  153. Aliases[std::move(AliasName)] = {ES.intern(KV.second),
  154. JITSymbolFlags::Exported};
  155. }
  156. }
  157. SymbolAliasMap ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES) {
  158. SymbolAliasMap Aliases;
  159. addAliases(ES, Aliases, requiredCXXAliases());
  160. addAliases(ES, Aliases, standardRuntimeUtilityAliases());
  161. return Aliases;
  162. }
  163. ArrayRef<std::pair<const char *, const char *>>
  164. ELFNixPlatform::requiredCXXAliases() {
  165. static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
  166. {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},
  167. {"atexit", "__orc_rt_elfnix_atexit"}};
  168. return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
  169. }
  170. ArrayRef<std::pair<const char *, const char *>>
  171. ELFNixPlatform::standardRuntimeUtilityAliases() {
  172. static const std::pair<const char *, const char *>
  173. StandardRuntimeUtilityAliases[] = {
  174. {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},
  175. {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
  176. return ArrayRef<std::pair<const char *, const char *>>(
  177. StandardRuntimeUtilityAliases);
  178. }
  179. bool ELFNixPlatform::isInitializerSection(StringRef SecName) {
  180. for (auto &Name : InitSectionNames) {
  181. if (Name.equals(SecName))
  182. return true;
  183. }
  184. return false;
  185. }
  186. bool ELFNixPlatform::supportedTarget(const Triple &TT) {
  187. switch (TT.getArch()) {
  188. case Triple::x86_64:
  189. return true;
  190. default:
  191. return false;
  192. }
  193. }
  194. ELFNixPlatform::ELFNixPlatform(
  195. ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  196. JITDylib &PlatformJD,
  197. std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
  198. : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
  199. DSOHandleSymbol(ES.intern("__dso_handle")) {
  200. ErrorAsOutParameter _(&Err);
  201. ObjLinkingLayer.addPlugin(std::make_unique<ELFNixPlatformPlugin>(*this));
  202. PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
  203. // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating
  204. // the platform now), so set it up.
  205. if (auto E2 = setupJITDylib(PlatformJD)) {
  206. Err = std::move(E2);
  207. return;
  208. }
  209. RegisteredInitSymbols[&PlatformJD].add(
  210. DSOHandleSymbol, SymbolLookupFlags::WeaklyReferencedSymbol);
  211. // Associate wrapper function tags with JIT-side function implementations.
  212. if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
  213. Err = std::move(E2);
  214. return;
  215. }
  216. // Lookup addresses of runtime functions callable by the platform,
  217. // call the platform bootstrap function to initialize the platform-state
  218. // object in the executor.
  219. if (auto E2 = bootstrapELFNixRuntime(PlatformJD)) {
  220. Err = std::move(E2);
  221. return;
  222. }
  223. }
  224. Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
  225. ExecutionSession::JITDispatchHandlerAssociationMap WFs;
  226. using GetInitializersSPSSig =
  227. SPSExpected<SPSELFNixJITDylibInitializerSequence>(SPSString);
  228. WFs[ES.intern("__orc_rt_elfnix_get_initializers_tag")] =
  229. ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
  230. this, &ELFNixPlatform::rt_getInitializers);
  231. using GetDeinitializersSPSSig =
  232. SPSExpected<SPSELFJITDylibDeinitializerSequence>(SPSExecutorAddr);
  233. WFs[ES.intern("__orc_rt_elfnix_get_deinitializers_tag")] =
  234. ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
  235. this, &ELFNixPlatform::rt_getDeinitializers);
  236. using LookupSymbolSPSSig =
  237. SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
  238. WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] =
  239. ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
  240. &ELFNixPlatform::rt_lookupSymbol);
  241. return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
  242. }
  243. void ELFNixPlatform::getInitializersBuildSequencePhase(
  244. SendInitializerSequenceFn SendResult, JITDylib &JD,
  245. std::vector<JITDylibSP> DFSLinkOrder) {
  246. ELFNixJITDylibInitializerSequence FullInitSeq;
  247. {
  248. std::lock_guard<std::mutex> Lock(PlatformMutex);
  249. for (auto &InitJD : reverse(DFSLinkOrder)) {
  250. LLVM_DEBUG({
  251. dbgs() << "ELFNixPlatform: Appending inits for \"" << InitJD->getName()
  252. << "\" to sequence\n";
  253. });
  254. auto ISItr = InitSeqs.find(InitJD.get());
  255. if (ISItr != InitSeqs.end()) {
  256. FullInitSeq.emplace_back(std::move(ISItr->second));
  257. InitSeqs.erase(ISItr);
  258. }
  259. }
  260. }
  261. SendResult(std::move(FullInitSeq));
  262. }
  263. void ELFNixPlatform::getInitializersLookupPhase(
  264. SendInitializerSequenceFn SendResult, JITDylib &JD) {
  265. auto DFSLinkOrder = JD.getDFSLinkOrder();
  266. if (!DFSLinkOrder) {
  267. SendResult(DFSLinkOrder.takeError());
  268. return;
  269. }
  270. DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
  271. ES.runSessionLocked([&]() {
  272. for (auto &InitJD : *DFSLinkOrder) {
  273. auto RISItr = RegisteredInitSymbols.find(InitJD.get());
  274. if (RISItr != RegisteredInitSymbols.end()) {
  275. NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
  276. RegisteredInitSymbols.erase(RISItr);
  277. }
  278. }
  279. });
  280. // If there are no further init symbols to look up then move on to the next
  281. // phase.
  282. if (NewInitSymbols.empty()) {
  283. getInitializersBuildSequencePhase(std::move(SendResult), JD,
  284. std::move(*DFSLinkOrder));
  285. return;
  286. }
  287. // Otherwise issue a lookup and re-run this phase when it completes.
  288. lookupInitSymbolsAsync(
  289. [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
  290. if (Err)
  291. SendResult(std::move(Err));
  292. else
  293. getInitializersLookupPhase(std::move(SendResult), JD);
  294. },
  295. ES, std::move(NewInitSymbols));
  296. }
  297. void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
  298. StringRef JDName) {
  299. LLVM_DEBUG({
  300. dbgs() << "ELFNixPlatform::rt_getInitializers(\"" << JDName << "\")\n";
  301. });
  302. JITDylib *JD = ES.getJITDylibByName(JDName);
  303. if (!JD) {
  304. LLVM_DEBUG({
  305. dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n";
  306. });
  307. SendResult(make_error<StringError>("No JITDylib named " + JDName,
  308. inconvertibleErrorCode()));
  309. return;
  310. }
  311. getInitializersLookupPhase(std::move(SendResult), *JD);
  312. }
  313. void ELFNixPlatform::rt_getDeinitializers(
  314. SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) {
  315. LLVM_DEBUG({
  316. dbgs() << "ELFNixPlatform::rt_getDeinitializers(\""
  317. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  318. });
  319. JITDylib *JD = nullptr;
  320. {
  321. std::lock_guard<std::mutex> Lock(PlatformMutex);
  322. auto I = HandleAddrToJITDylib.find(Handle);
  323. if (I != HandleAddrToJITDylib.end())
  324. JD = I->second;
  325. }
  326. if (!JD) {
  327. LLVM_DEBUG({
  328. dbgs() << " No JITDylib for handle "
  329. << formatv("{0:x}", Handle.getValue()) << "\n";
  330. });
  331. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  332. formatv("{0:x}", Handle.getValue()),
  333. inconvertibleErrorCode()));
  334. return;
  335. }
  336. SendResult(ELFNixJITDylibDeinitializerSequence());
  337. }
  338. void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
  339. ExecutorAddr Handle,
  340. StringRef SymbolName) {
  341. LLVM_DEBUG({
  342. dbgs() << "ELFNixPlatform::rt_lookupSymbol(\""
  343. << formatv("{0:x}", Handle.getValue()) << "\")\n";
  344. });
  345. JITDylib *JD = nullptr;
  346. {
  347. std::lock_guard<std::mutex> Lock(PlatformMutex);
  348. auto I = HandleAddrToJITDylib.find(Handle);
  349. if (I != HandleAddrToJITDylib.end())
  350. JD = I->second;
  351. }
  352. if (!JD) {
  353. LLVM_DEBUG({
  354. dbgs() << " No JITDylib for handle "
  355. << formatv("{0:x}", Handle.getValue()) << "\n";
  356. });
  357. SendResult(make_error<StringError>("No JITDylib associated with handle " +
  358. formatv("{0:x}", Handle.getValue()),
  359. inconvertibleErrorCode()));
  360. return;
  361. }
  362. // Use functor class to work around XL build compiler issue on AIX.
  363. class RtLookupNotifyComplete {
  364. public:
  365. RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
  366. : SendResult(std::move(SendResult)) {}
  367. void operator()(Expected<SymbolMap> Result) {
  368. if (Result) {
  369. assert(Result->size() == 1 && "Unexpected result map count");
  370. SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
  371. } else {
  372. SendResult(Result.takeError());
  373. }
  374. }
  375. private:
  376. SendSymbolAddressFn SendResult;
  377. };
  378. ES.lookup(
  379. LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
  380. SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
  381. RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
  382. }
  383. Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
  384. std::pair<const char *, ExecutorAddr *> Symbols[] = {
  385. {"__orc_rt_elfnix_platform_bootstrap", &orc_rt_elfnix_platform_bootstrap},
  386. {"__orc_rt_elfnix_platform_shutdown", &orc_rt_elfnix_platform_shutdown},
  387. {"__orc_rt_elfnix_register_object_sections",
  388. &orc_rt_elfnix_register_object_sections},
  389. {"__orc_rt_elfnix_create_pthread_key",
  390. &orc_rt_elfnix_create_pthread_key}};
  391. SymbolLookupSet RuntimeSymbols;
  392. std::vector<std::pair<SymbolStringPtr, ExecutorAddr *>> AddrsToRecord;
  393. for (const auto &KV : Symbols) {
  394. auto Name = ES.intern(KV.first);
  395. RuntimeSymbols.add(Name);
  396. AddrsToRecord.push_back({std::move(Name), KV.second});
  397. }
  398. auto RuntimeSymbolAddrs = ES.lookup(
  399. {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
  400. if (!RuntimeSymbolAddrs)
  401. return RuntimeSymbolAddrs.takeError();
  402. for (const auto &KV : AddrsToRecord) {
  403. auto &Name = KV.first;
  404. assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
  405. KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
  406. }
  407. auto PJDDSOHandle = ES.lookup(
  408. {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol);
  409. if (!PJDDSOHandle)
  410. return PJDDSOHandle.takeError();
  411. if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
  412. orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress()))
  413. return Err;
  414. // FIXME: Ordering is fuzzy here. We're probably best off saying
  415. // "behavior is undefined if code that uses the runtime is added before
  416. // the platform constructor returns", then move all this to the constructor.
  417. RuntimeBootstrapped = true;
  418. std::vector<ELFPerObjectSectionsToRegister> DeferredPOSRs;
  419. {
  420. std::lock_guard<std::mutex> Lock(PlatformMutex);
  421. DeferredPOSRs = std::move(BootstrapPOSRs);
  422. }
  423. for (auto &D : DeferredPOSRs)
  424. if (auto Err = registerPerObjectSections(D))
  425. return Err;
  426. return Error::success();
  427. }
  428. Error ELFNixPlatform::registerInitInfo(
  429. JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) {
  430. std::unique_lock<std::mutex> Lock(PlatformMutex);
  431. ELFNixJITDylibInitializers *InitSeq = nullptr;
  432. {
  433. auto I = InitSeqs.find(&JD);
  434. if (I == InitSeqs.end()) {
  435. // If there's no init sequence entry yet then we need to look up the
  436. // header symbol to force creation of one.
  437. Lock.unlock();
  438. auto SearchOrder =
  439. JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; });
  440. if (auto Err = ES.lookup(SearchOrder, DSOHandleSymbol).takeError())
  441. return Err;
  442. Lock.lock();
  443. I = InitSeqs.find(&JD);
  444. assert(I != InitSeqs.end() &&
  445. "Entry missing after header symbol lookup?");
  446. }
  447. InitSeq = &I->second;
  448. }
  449. for (auto *Sec : InitSections) {
  450. // FIXME: Avoid copy here.
  451. jitlink::SectionRange R(*Sec);
  452. InitSeq->InitSections[Sec->getName()].push_back(
  453. {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())});
  454. }
  455. return Error::success();
  456. }
  457. Error ELFNixPlatform::registerPerObjectSections(
  458. const ELFPerObjectSectionsToRegister &POSR) {
  459. if (!orc_rt_elfnix_register_object_sections)
  460. return make_error<StringError>("Attempting to register per-object "
  461. "sections, but runtime support has not "
  462. "been loaded yet",
  463. inconvertibleErrorCode());
  464. Error ErrResult = Error::success();
  465. if (auto Err = ES.callSPSWrapper<shared::SPSError(
  466. SPSELFPerObjectSectionsToRegister)>(
  467. orc_rt_elfnix_register_object_sections, ErrResult, POSR))
  468. return Err;
  469. return ErrResult;
  470. }
  471. Expected<uint64_t> ELFNixPlatform::createPThreadKey() {
  472. if (!orc_rt_elfnix_create_pthread_key)
  473. return make_error<StringError>(
  474. "Attempting to create pthread key in target, but runtime support has "
  475. "not been loaded yet",
  476. inconvertibleErrorCode());
  477. Expected<uint64_t> Result(0);
  478. if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
  479. orc_rt_elfnix_create_pthread_key, Result))
  480. return std::move(Err);
  481. return Result;
  482. }
  483. void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig(
  484. MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
  485. jitlink::PassConfiguration &Config) {
  486. // If the initializer symbol is the __dso_handle symbol then just add
  487. // the DSO handle support passes.
  488. if (MR.getInitializerSymbol() == MP.DSOHandleSymbol) {
  489. addDSOHandleSupportPasses(MR, Config);
  490. // The DSOHandle materialization unit doesn't require any other
  491. // support, so we can bail out early.
  492. return;
  493. }
  494. // If the object contains initializers then add passes to record them.
  495. if (MR.getInitializerSymbol())
  496. addInitializerSupportPasses(MR, Config);
  497. // Add passes for eh-frame and TLV support.
  498. addEHAndTLVSupportPasses(MR, Config);
  499. }
  500. ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
  501. ELFNixPlatform::ELFNixPlatformPlugin::getSyntheticSymbolDependencies(
  502. MaterializationResponsibility &MR) {
  503. std::lock_guard<std::mutex> Lock(PluginMutex);
  504. auto I = InitSymbolDeps.find(&MR);
  505. if (I != InitSymbolDeps.end()) {
  506. SyntheticSymbolDependenciesMap Result;
  507. Result[MR.getInitializerSymbol()] = std::move(I->second);
  508. InitSymbolDeps.erase(&MR);
  509. return Result;
  510. }
  511. return SyntheticSymbolDependenciesMap();
  512. }
  513. void ELFNixPlatform::ELFNixPlatformPlugin::addInitializerSupportPasses(
  514. MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
  515. /// Preserve init sections.
  516. Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
  517. if (auto Err = preserveInitSections(G, MR))
  518. return Err;
  519. return Error::success();
  520. });
  521. Config.PostFixupPasses.push_back(
  522. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  523. return registerInitSections(G, JD);
  524. });
  525. }
  526. void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses(
  527. MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
  528. Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()](
  529. jitlink::LinkGraph &G) -> Error {
  530. auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
  531. return Sym->getName() == *MP.DSOHandleSymbol;
  532. });
  533. assert(I != G.defined_symbols().end() && "Missing DSO handle symbol");
  534. {
  535. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  536. auto HandleAddr = (*I)->getAddress();
  537. MP.HandleAddrToJITDylib[HandleAddr] = &JD;
  538. assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists");
  539. MP.InitSeqs.insert(std::make_pair(
  540. &JD, ELFNixJITDylibInitializers(JD.getName(), HandleAddr)));
  541. }
  542. return Error::success();
  543. });
  544. }
  545. void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
  546. MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
  547. // Insert TLV lowering at the start of the PostPrunePasses, since we want
  548. // it to run before GOT/PLT lowering.
  549. // TODO: Check that before the fixTLVSectionsAndEdges pass, the GOT/PLT build
  550. // pass has done. Because the TLS descriptor need to be allocate in GOT.
  551. Config.PostPrunePasses.push_back(
  552. [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
  553. return fixTLVSectionsAndEdges(G, JD);
  554. });
  555. // Add a pass to register the final addresses of the eh-frame and TLV sections
  556. // with the runtime.
  557. Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
  558. ELFPerObjectSectionsToRegister POSR;
  559. if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
  560. jitlink::SectionRange R(*EHFrameSection);
  561. if (!R.empty())
  562. POSR.EHFrameSection = {ExecutorAddr(R.getStart()),
  563. ExecutorAddr(R.getEnd())};
  564. }
  565. // Get a pointer to the thread data section if there is one. It will be used
  566. // below.
  567. jitlink::Section *ThreadDataSection =
  568. G.findSectionByName(ThreadDataSectionName);
  569. // Handle thread BSS section if there is one.
  570. if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
  571. // If there's already a thread data section in this graph then merge the
  572. // thread BSS section content into it, otherwise just treat the thread
  573. // BSS section as the thread data section.
  574. if (ThreadDataSection)
  575. G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
  576. else
  577. ThreadDataSection = ThreadBSSSection;
  578. }
  579. // Having merged thread BSS (if present) and thread data (if present),
  580. // record the resulting section range.
  581. if (ThreadDataSection) {
  582. jitlink::SectionRange R(*ThreadDataSection);
  583. if (!R.empty())
  584. POSR.ThreadDataSection = {ExecutorAddr(R.getStart()),
  585. ExecutorAddr(R.getEnd())};
  586. }
  587. if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) {
  588. // If we're still bootstrapping the runtime then just record this
  589. // frame for now.
  590. if (!MP.RuntimeBootstrapped) {
  591. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  592. MP.BootstrapPOSRs.push_back(POSR);
  593. return Error::success();
  594. }
  595. // Otherwise register it immediately.
  596. if (auto Err = MP.registerPerObjectSections(POSR))
  597. return Err;
  598. }
  599. return Error::success();
  600. });
  601. }
  602. Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(
  603. jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  604. JITLinkSymbolSet InitSectionSymbols;
  605. for (auto &InitSectionName : InitSectionNames) {
  606. // Skip non-init sections.
  607. auto *InitSection = G.findSectionByName(InitSectionName);
  608. if (!InitSection)
  609. continue;
  610. // Make a pass over live symbols in the section: those blocks are already
  611. // preserved.
  612. DenseSet<jitlink::Block *> AlreadyLiveBlocks;
  613. for (auto &Sym : InitSection->symbols()) {
  614. auto &B = Sym->getBlock();
  615. if (Sym->isLive() && Sym->getOffset() == 0 &&
  616. Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
  617. InitSectionSymbols.insert(Sym);
  618. AlreadyLiveBlocks.insert(&B);
  619. }
  620. }
  621. // Add anonymous symbols to preserve any not-already-preserved blocks.
  622. for (auto *B : InitSection->blocks())
  623. if (!AlreadyLiveBlocks.count(B))
  624. InitSectionSymbols.insert(
  625. &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
  626. }
  627. if (!InitSectionSymbols.empty()) {
  628. std::lock_guard<std::mutex> Lock(PluginMutex);
  629. InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
  630. }
  631. return Error::success();
  632. }
  633. Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
  634. jitlink::LinkGraph &G, JITDylib &JD) {
  635. SmallVector<jitlink::Section *> InitSections;
  636. LLVM_DEBUG({ dbgs() << "ELFNixPlatform::registerInitSections\n"; });
  637. for (auto InitSectionName : InitSectionNames) {
  638. if (auto *Sec = G.findSectionByName(InitSectionName)) {
  639. InitSections.push_back(Sec);
  640. }
  641. }
  642. // Dump the scraped inits.
  643. LLVM_DEBUG({
  644. dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";
  645. for (auto *Sec : InitSections) {
  646. jitlink::SectionRange R(*Sec);
  647. dbgs() << " " << Sec->getName() << ": "
  648. << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n";
  649. }
  650. });
  651. return MP.registerInitInfo(JD, InitSections);
  652. }
  653. Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
  654. jitlink::LinkGraph &G, JITDylib &JD) {
  655. // TODO implement TLV support
  656. for (auto *Sym : G.external_symbols())
  657. if (Sym->getName() == "__tls_get_addr") {
  658. Sym->setName("___orc_rt_elfnix_tls_get_addr");
  659. }
  660. auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
  661. if (TLSInfoEntrySection) {
  662. Optional<uint64_t> Key;
  663. {
  664. std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
  665. auto I = MP.JITDylibToPThreadKey.find(&JD);
  666. if (I != MP.JITDylibToPThreadKey.end())
  667. Key = I->second;
  668. }
  669. if (!Key) {
  670. if (auto KeyOrErr = MP.createPThreadKey())
  671. Key = *KeyOrErr;
  672. else
  673. return KeyOrErr.takeError();
  674. }
  675. uint64_t PlatformKeyBits =
  676. support::endian::byte_swap(*Key, G.getEndianness());
  677. for (auto *B : TLSInfoEntrySection->blocks()) {
  678. // FIXME: The TLS descriptor byte length may different with different
  679. // ISA
  680. assert(B->getSize() == (G.getPointerSize() * 2) &&
  681. "TLS descriptor must be 2 words length");
  682. auto TLSInfoEntryContent = B->getMutableContent(G);
  683. memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize());
  684. }
  685. }
  686. return Error::success();
  687. }
  688. } // End namespace orc.
  689. } // End namespace llvm.