ELFNixPlatform.cpp 30 KB

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