1 //===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 10 11 #include "llvm/BinaryFormat/MachO.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 18 #define DEBUG_TYPE "orc" 19 20 using namespace llvm; 21 using namespace llvm::orc; 22 using namespace llvm::orc::shared; 23 24 namespace { 25 26 class MachOHeaderMaterializationUnit : public MaterializationUnit { 27 public: 28 MachOHeaderMaterializationUnit(MachOPlatform &MOP, 29 const SymbolStringPtr &HeaderStartSymbol) 30 : MaterializationUnit(createHeaderSymbols(MOP, HeaderStartSymbol), 31 HeaderStartSymbol), 32 MOP(MOP) {} 33 34 StringRef getName() const override { return "MachOHeaderMU"; } 35 36 void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 37 unsigned PointerSize; 38 support::endianness Endianness; 39 40 switch (MOP.getExecutorProcessControl().getTargetTriple().getArch()) { 41 case Triple::aarch64: 42 case Triple::x86_64: 43 PointerSize = 8; 44 Endianness = support::endianness::little; 45 break; 46 default: 47 llvm_unreachable("Unrecognized architecture"); 48 } 49 50 auto G = std::make_unique<jitlink::LinkGraph>( 51 "<MachOHeaderMU>", MOP.getExecutorProcessControl().getTargetTriple(), 52 PointerSize, Endianness, jitlink::getGenericEdgeKindName); 53 auto &HeaderSection = G->createSection("__header", sys::Memory::MF_READ); 54 auto &HeaderBlock = createHeaderBlock(*G, HeaderSection); 55 56 // Init symbol is header-start symbol. 57 G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(), 58 HeaderBlock.getSize(), jitlink::Linkage::Strong, 59 jitlink::Scope::Default, false, true); 60 for (auto &HS : AdditionalHeaderSymbols) 61 G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, 62 HeaderBlock.getSize(), jitlink::Linkage::Strong, 63 jitlink::Scope::Default, false, true); 64 65 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 66 } 67 68 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 69 70 private: 71 struct HeaderSymbol { 72 const char *Name; 73 uint64_t Offset; 74 }; 75 76 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = { 77 {"___mh_executable_header", 0}}; 78 79 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G, 80 jitlink::Section &HeaderSection) { 81 MachO::mach_header_64 Hdr; 82 Hdr.magic = MachO::MH_MAGIC_64; 83 switch (G.getTargetTriple().getArch()) { 84 case Triple::aarch64: 85 Hdr.cputype = MachO::CPU_TYPE_ARM64; 86 Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 87 break; 88 case Triple::x86_64: 89 Hdr.cputype = MachO::CPU_TYPE_X86_64; 90 Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 91 break; 92 default: 93 llvm_unreachable("Unrecognized architecture"); 94 } 95 Hdr.filetype = MachO::MH_DYLIB; // Custom file type? 96 Hdr.ncmds = 0; 97 Hdr.sizeofcmds = 0; 98 Hdr.flags = 0; 99 Hdr.reserved = 0; 100 101 if (G.getEndianness() != support::endian::system_endianness()) 102 MachO::swapStruct(Hdr); 103 104 auto HeaderContent = G.allocateString( 105 StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr))); 106 107 return G.createContentBlock(HeaderSection, HeaderContent, 0, 8, 0); 108 } 109 110 static SymbolFlagsMap 111 createHeaderSymbols(MachOPlatform &MOP, 112 const SymbolStringPtr &HeaderStartSymbol) { 113 SymbolFlagsMap HeaderSymbolFlags; 114 115 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 116 for (auto &HS : AdditionalHeaderSymbols) 117 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = 118 JITSymbolFlags::Exported; 119 120 return HeaderSymbolFlags; 121 } 122 123 MachOPlatform &MOP; 124 }; 125 126 constexpr MachOHeaderMaterializationUnit::HeaderSymbol 127 MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[]; 128 129 StringRef EHFrameSectionName = "__TEXT,__eh_frame"; 130 StringRef ModInitFuncSectionName = "__DATA,__mod_init_func"; 131 132 StringRef InitSectionNames[] = {ModInitFuncSectionName}; 133 134 } // end anonymous namespace 135 136 namespace llvm { 137 namespace orc { 138 139 Expected<std::unique_ptr<MachOPlatform>> 140 MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 141 ExecutorProcessControl &EPC, JITDylib &PlatformJD, 142 const char *OrcRuntimePath, 143 Optional<SymbolAliasMap> RuntimeAliases) { 144 145 // If the target is not supported then bail out immediately. 146 if (!supportedTarget(EPC.getTargetTriple())) 147 return make_error<StringError>("Unsupported MachOPlatform triple: " + 148 EPC.getTargetTriple().str(), 149 inconvertibleErrorCode()); 150 151 // Create default aliases if the caller didn't supply any. 152 if (!RuntimeAliases) 153 RuntimeAliases = standardPlatformAliases(ES); 154 155 // Define the aliases. 156 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 157 return std::move(Err); 158 159 // Add JIT-dispatch function support symbols. 160 if (auto Err = PlatformJD.define(absoluteSymbols( 161 {{ES.intern("___orc_rt_jit_dispatch"), 162 {EPC.getJITDispatchInfo().JITDispatchFunctionAddress.getValue(), 163 JITSymbolFlags::Exported}}, 164 {ES.intern("___orc_rt_jit_dispatch_ctx"), 165 {EPC.getJITDispatchInfo().JITDispatchContextAddress.getValue(), 166 JITSymbolFlags::Exported}}}))) 167 return std::move(Err); 168 169 // Create a generator for the ORC runtime archive. 170 auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load( 171 ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple()); 172 if (!OrcRuntimeArchiveGenerator) 173 return OrcRuntimeArchiveGenerator.takeError(); 174 175 // Create the instance. 176 Error Err = Error::success(); 177 auto P = std::unique_ptr<MachOPlatform>( 178 new MachOPlatform(ES, ObjLinkingLayer, EPC, PlatformJD, 179 std::move(*OrcRuntimeArchiveGenerator), Err)); 180 if (Err) 181 return std::move(Err); 182 return std::move(P); 183 } 184 185 Error MachOPlatform::setupJITDylib(JITDylib &JD) { 186 return JD.define(std::make_unique<MachOHeaderMaterializationUnit>( 187 *this, MachOHeaderStartSymbol)); 188 } 189 190 Error MachOPlatform::notifyAdding(ResourceTracker &RT, 191 const MaterializationUnit &MU) { 192 auto &JD = RT.getJITDylib(); 193 const auto &InitSym = MU.getInitializerSymbol(); 194 if (!InitSym) 195 return Error::success(); 196 197 RegisteredInitSymbols[&JD].add(InitSym, 198 SymbolLookupFlags::WeaklyReferencedSymbol); 199 LLVM_DEBUG({ 200 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU " 201 << MU.getName() << "\n"; 202 }); 203 return Error::success(); 204 } 205 206 Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { 207 llvm_unreachable("Not supported yet"); 208 } 209 210 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 211 ArrayRef<std::pair<const char *, const char *>> AL) { 212 for (auto &KV : AL) { 213 auto AliasName = ES.intern(KV.first); 214 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 215 Aliases[std::move(AliasName)] = {ES.intern(KV.second), 216 JITSymbolFlags::Exported}; 217 } 218 } 219 220 SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { 221 SymbolAliasMap Aliases; 222 addAliases(ES, Aliases, requiredCXXAliases()); 223 addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 224 return Aliases; 225 } 226 227 ArrayRef<std::pair<const char *, const char *>> 228 MachOPlatform::requiredCXXAliases() { 229 static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 230 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; 231 232 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 233 } 234 235 ArrayRef<std::pair<const char *, const char *>> 236 MachOPlatform::standardRuntimeUtilityAliases() { 237 static const std::pair<const char *, const char *> 238 StandardRuntimeUtilityAliases[] = { 239 {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, 240 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; 241 242 return ArrayRef<std::pair<const char *, const char *>>( 243 StandardRuntimeUtilityAliases); 244 } 245 246 bool MachOPlatform::supportedTarget(const Triple &TT) { 247 switch (TT.getArch()) { 248 case Triple::x86_64: 249 return true; 250 default: 251 return false; 252 } 253 } 254 255 MachOPlatform::MachOPlatform( 256 ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 257 ExecutorProcessControl &EPC, JITDylib &PlatformJD, 258 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err) 259 : ES(ES), ObjLinkingLayer(ObjLinkingLayer), EPC(EPC), 260 MachOHeaderStartSymbol(ES.intern("___dso_handle")) { 261 ErrorAsOutParameter _(&Err); 262 263 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this)); 264 265 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 266 267 // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating 268 // the platform now), so set it up. 269 if (auto E2 = setupJITDylib(PlatformJD)) { 270 Err = std::move(E2); 271 return; 272 } 273 274 RegisteredInitSymbols[&PlatformJD].add( 275 MachOHeaderStartSymbol, SymbolLookupFlags::WeaklyReferencedSymbol); 276 277 // Associate wrapper function tags with JIT-side function implementations. 278 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) { 279 Err = std::move(E2); 280 return; 281 } 282 283 // Lookup addresses of runtime functions callable by the platform, 284 // call the platform bootstrap function to initialize the platform-state 285 // object in the executor. 286 if (auto E2 = bootstrapMachORuntime(PlatformJD)) { 287 Err = std::move(E2); 288 return; 289 } 290 } 291 292 Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) { 293 ExecutorProcessControl::WrapperFunctionAssociationMap WFs; 294 295 using GetInitializersSPSSig = 296 SPSExpected<SPSMachOJITDylibInitializerSequence>(SPSString); 297 WFs[ES.intern("___orc_rt_macho_get_initializers_tag")] = 298 EPC.wrapAsyncWithSPS<GetInitializersSPSSig>( 299 this, &MachOPlatform::rt_getInitializers); 300 301 using GetDeinitializersSPSSig = 302 SPSExpected<SPSMachOJITDylibDeinitializerSequence>(SPSExecutorAddress); 303 WFs[ES.intern("___orc_rt_macho_get_deinitializers_tag")] = 304 EPC.wrapAsyncWithSPS<GetDeinitializersSPSSig>( 305 this, &MachOPlatform::rt_getDeinitializers); 306 307 using LookupSymbolSPSSig = 308 SPSExpected<SPSExecutorAddress>(SPSExecutorAddress, SPSString); 309 WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] = 310 EPC.wrapAsyncWithSPS<LookupSymbolSPSSig>(this, 311 &MachOPlatform::rt_lookupSymbol); 312 313 return EPC.associateJITSideWrapperFunctions(PlatformJD, std::move(WFs)); 314 } 315 316 void MachOPlatform::getInitializersBuildSequencePhase( 317 SendInitializerSequenceFn SendResult, JITDylib &JD, 318 std::vector<JITDylibSP> DFSLinkOrder) { 319 MachOJITDylibInitializerSequence FullInitSeq; 320 { 321 std::lock_guard<std::mutex> Lock(PlatformMutex); 322 for (auto &InitJD : reverse(DFSLinkOrder)) { 323 LLVM_DEBUG({ 324 dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName() 325 << "\" to sequence\n"; 326 }); 327 auto ISItr = InitSeqs.find(InitJD.get()); 328 if (ISItr != InitSeqs.end()) { 329 FullInitSeq.emplace_back(std::move(ISItr->second)); 330 InitSeqs.erase(ISItr); 331 } 332 } 333 } 334 335 SendResult(std::move(FullInitSeq)); 336 } 337 338 void MachOPlatform::getInitializersLookupPhase( 339 SendInitializerSequenceFn SendResult, JITDylib &JD) { 340 341 auto DFSLinkOrder = JD.getDFSLinkOrder(); 342 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 343 ES.runSessionLocked([&]() { 344 for (auto &InitJD : DFSLinkOrder) { 345 auto RISItr = RegisteredInitSymbols.find(InitJD.get()); 346 if (RISItr != RegisteredInitSymbols.end()) { 347 NewInitSymbols[InitJD.get()] = std::move(RISItr->second); 348 RegisteredInitSymbols.erase(RISItr); 349 } 350 } 351 }); 352 353 // If there are no further init symbols to look up then move on to the next 354 // phase. 355 if (NewInitSymbols.empty()) { 356 getInitializersBuildSequencePhase(std::move(SendResult), JD, 357 std::move(DFSLinkOrder)); 358 return; 359 } 360 361 // Otherwise issue a lookup and re-run this phase when it completes. 362 lookupInitSymbolsAsync( 363 [this, SendResult = std::move(SendResult), &JD](Error Err) mutable { 364 if (Err) 365 SendResult(std::move(Err)); 366 else 367 getInitializersLookupPhase(std::move(SendResult), JD); 368 }, 369 ES, std::move(NewInitSymbols)); 370 } 371 372 void MachOPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult, 373 StringRef JDName) { 374 LLVM_DEBUG({ 375 dbgs() << "MachOPlatform::rt_getInitializers(\"" << JDName << "\")\n"; 376 }); 377 378 JITDylib *JD = ES.getJITDylibByName(JDName); 379 if (!JD) { 380 LLVM_DEBUG({ 381 dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n"; 382 }); 383 SendResult(make_error<StringError>("No JITDylib named " + JDName, 384 inconvertibleErrorCode())); 385 return; 386 } 387 388 getInitializersLookupPhase(std::move(SendResult), *JD); 389 } 390 391 void MachOPlatform::rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, 392 ExecutorAddress Handle) { 393 LLVM_DEBUG({ 394 dbgs() << "MachOPlatform::rt_getDeinitializers(\"" 395 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 396 }); 397 398 JITDylib *JD = nullptr; 399 400 { 401 std::lock_guard<std::mutex> Lock(PlatformMutex); 402 auto I = HeaderAddrToJITDylib.find(Handle.getValue()); 403 if (I != HeaderAddrToJITDylib.end()) 404 JD = I->second; 405 } 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 418 SendResult(MachOJITDylibDeinitializerSequence()); 419 } 420 421 void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 422 ExecutorAddress Handle, 423 StringRef SymbolName) { 424 LLVM_DEBUG({ 425 dbgs() << "MachOPlatform::rt_lookupSymbol(\"" 426 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 427 }); 428 429 JITDylib *JD = nullptr; 430 431 { 432 std::lock_guard<std::mutex> Lock(PlatformMutex); 433 auto I = HeaderAddrToJITDylib.find(Handle.getValue()); 434 if (I != HeaderAddrToJITDylib.end()) 435 JD = I->second; 436 } 437 438 if (!JD) { 439 LLVM_DEBUG({ 440 dbgs() << " No JITDylib for handle " 441 << formatv("{0:x}", Handle.getValue()) << "\n"; 442 }); 443 SendResult(make_error<StringError>("No JITDylib associated with handle " + 444 formatv("{0:x}", Handle.getValue()), 445 inconvertibleErrorCode())); 446 return; 447 } 448 449 // Use functor class to work around XL build compiler issue on AIX. 450 class RtLookupNotifyComplete { 451 public: 452 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 453 : SendResult(std::move(SendResult)) {} 454 void operator()(Expected<SymbolMap> Result) { 455 if (Result) { 456 assert(Result->size() == 1 && "Unexpected result map count"); 457 SendResult(ExecutorAddress(Result->begin()->second.getAddress())); 458 } else { 459 SendResult(Result.takeError()); 460 } 461 } 462 463 private: 464 SendSymbolAddressFn SendResult; 465 }; 466 467 // FIXME: Proper mangling. 468 auto MangledName = ("_" + SymbolName).str(); 469 ES.lookup( 470 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 471 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, 472 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 473 } 474 475 Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) { 476 477 std::pair<const char *, ExecutorAddress *> Symbols[] = { 478 {"___orc_rt_macho_platform_bootstrap", &orc_rt_macho_platform_bootstrap}, 479 {"___orc_rt_macho_platform_shutdown", &orc_rt_macho_platform_shutdown}, 480 {"___orc_rt_macho_register_object_sections", 481 &orc_rt_macho_register_object_sections}}; 482 483 SymbolLookupSet RuntimeSymbols; 484 std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> AddrsToRecord; 485 for (const auto &KV : Symbols) { 486 auto Name = ES.intern(KV.first); 487 RuntimeSymbols.add(Name); 488 AddrsToRecord.push_back({std::move(Name), KV.second}); 489 } 490 491 auto RuntimeSymbolAddrs = ES.lookup( 492 {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols); 493 if (!RuntimeSymbolAddrs) 494 return RuntimeSymbolAddrs.takeError(); 495 496 for (const auto &KV : AddrsToRecord) { 497 auto &Name = KV.first; 498 assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?"); 499 KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress()); 500 } 501 502 if (auto Err = 503 EPC.runSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue())) 504 return Err; 505 506 // FIXME: Ordering is fuzzy here. We're probably best off saying 507 // "behavior is undefined if code that uses the runtime is added before 508 // the platform constructor returns", then move all this to the constructor. 509 RuntimeBootstrapped = true; 510 std::vector<MachOPerObjectSectionsToRegister> DeferredPOSRs; 511 { 512 std::lock_guard<std::mutex> Lock(PlatformMutex); 513 DeferredPOSRs = std::move(BootstrapPOSRs); 514 } 515 516 for (auto &D : DeferredPOSRs) 517 if (auto Err = registerPerObjectSections(D)) 518 return Err; 519 520 return Error::success(); 521 } 522 523 Error MachOPlatform::registerInitInfo( 524 JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) { 525 526 std::unique_lock<std::mutex> Lock(PlatformMutex); 527 528 MachOJITDylibInitializers *InitSeq = nullptr; 529 { 530 auto I = InitSeqs.find(&JD); 531 if (I == InitSeqs.end()) { 532 // If there's no init sequence entry yet then we need to look up the 533 // header symbol to force creation of one. 534 Lock.unlock(); 535 536 auto SearchOrder = 537 JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); 538 if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError()) 539 return Err; 540 541 Lock.lock(); 542 I = InitSeqs.find(&JD); 543 assert(I != InitSeqs.end() && 544 "Entry missing after header symbol lookup?"); 545 } 546 InitSeq = &I->second; 547 } 548 549 for (auto *Sec : InitSections) { 550 // FIXME: Avoid copy here. 551 jitlink::SectionRange R(*Sec); 552 InitSeq->InitSections[Sec->getName()].push_back( 553 {ExecutorAddress(R.getStart()), ExecutorAddress(R.getEnd())}); 554 } 555 556 return Error::success(); 557 } 558 559 Error MachOPlatform::registerPerObjectSections( 560 const MachOPerObjectSectionsToRegister &POSR) { 561 562 if (!orc_rt_macho_register_object_sections) 563 return make_error<StringError>("Attempting to register per-object " 564 "sections, but runtime support has not " 565 "been loaded yet", 566 inconvertibleErrorCode()); 567 568 Error ErrResult = Error::success(); 569 if (auto Err = EPC.runSPSWrapper<shared::SPSError( 570 SPSMachOPerObjectSectionsToRegister)>( 571 orc_rt_macho_register_object_sections.getValue(), ErrResult, POSR)) 572 return Err; 573 return ErrResult; 574 } 575 576 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 577 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 578 jitlink::PassConfiguration &Config) { 579 580 // If the initializer symbol is the MachOHeader start symbol then just add 581 // the macho header support passes. 582 if (MR.getInitializerSymbol() == MP.MachOHeaderStartSymbol) { 583 addMachOHeaderSupportPasses(MR, Config); 584 // The header materialization unit doesn't require any other support, so we 585 // can bail out early. 586 return; 587 } 588 589 // If the object contains initializers then add passes to record them. 590 if (MR.getInitializerSymbol()) 591 addInitializerSupportPasses(MR, Config); 592 593 // Add passes for eh-frame support. 594 addEHSupportPasses(MR, Config); 595 } 596 597 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 598 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 599 MaterializationResponsibility &MR) { 600 std::lock_guard<std::mutex> Lock(PluginMutex); 601 auto I = InitSymbolDeps.find(&MR); 602 if (I != InitSymbolDeps.end()) { 603 SyntheticSymbolDependenciesMap Result; 604 Result[MR.getInitializerSymbol()] = std::move(I->second); 605 InitSymbolDeps.erase(&MR); 606 return Result; 607 } 608 return SyntheticSymbolDependenciesMap(); 609 } 610 611 void MachOPlatform::MachOPlatformPlugin::addInitializerSupportPasses( 612 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 613 614 /// Preserve init sections. 615 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { 616 return preserveInitSections(G, MR); 617 }); 618 619 Config.PostFixupPasses.push_back( 620 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 621 return registerInitSections(G, JD); 622 }); 623 } 624 625 void MachOPlatform::MachOPlatformPlugin::addMachOHeaderSupportPasses( 626 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 627 628 Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()]( 629 jitlink::LinkGraph &G) -> Error { 630 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 631 return Sym->getName() == *MP.MachOHeaderStartSymbol; 632 }); 633 assert(I != G.defined_symbols().end() && 634 "Missing MachO header start symbol"); 635 { 636 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 637 JITTargetAddress HeaderAddr = (*I)->getAddress(); 638 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 639 assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); 640 MP.InitSeqs.insert( 641 std::make_pair(&JD, MachOJITDylibInitializers( 642 JD.getName(), ExecutorAddress(HeaderAddr)))); 643 } 644 return Error::success(); 645 }); 646 } 647 648 void MachOPlatform::MachOPlatformPlugin::addEHSupportPasses( 649 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 650 651 // Add a pass to register the final addresses of the eh-frame sections 652 // with the runtime. 653 Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { 654 MachOPerObjectSectionsToRegister POSR; 655 656 if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { 657 jitlink::SectionRange R(*EHFrameSection); 658 if (!R.empty()) 659 POSR.EHFrameSection = {ExecutorAddress(R.getStart()), 660 ExecutorAddress(R.getEnd())}; 661 } 662 663 if (POSR.EHFrameSection.StartAddress) { 664 665 // If we're still bootstrapping the runtime then just record this 666 // frame for now. 667 if (!MP.RuntimeBootstrapped) { 668 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 669 MP.BootstrapPOSRs.push_back(POSR); 670 return Error::success(); 671 } 672 673 // Otherwise register it immediately. 674 if (auto Err = MP.registerPerObjectSections(POSR)) 675 return Err; 676 } 677 678 return Error::success(); 679 }); 680 } 681 682 Error MachOPlatform::MachOPlatformPlugin::preserveInitSections( 683 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 684 685 JITLinkSymbolSet InitSectionSymbols; 686 for (auto &InitSectionName : InitSectionNames) { 687 // Skip non-init sections. 688 auto *InitSection = G.findSectionByName(InitSectionName); 689 if (!InitSection) 690 continue; 691 692 // Make a pass over live symbols in the section: those blocks are already 693 // preserved. 694 DenseSet<jitlink::Block *> AlreadyLiveBlocks; 695 for (auto &Sym : InitSection->symbols()) { 696 auto &B = Sym->getBlock(); 697 if (Sym->isLive() && Sym->getOffset() == 0 && 698 Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 699 InitSectionSymbols.insert(Sym); 700 AlreadyLiveBlocks.insert(&B); 701 } 702 } 703 704 // Add anonymous symbols to preserve any not-already-preserved blocks. 705 for (auto *B : InitSection->blocks()) 706 if (!AlreadyLiveBlocks.count(B)) 707 InitSectionSymbols.insert( 708 &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 709 } 710 711 if (!InitSectionSymbols.empty()) { 712 std::lock_guard<std::mutex> Lock(PluginMutex); 713 InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 714 } 715 716 return Error::success(); 717 } 718 719 Error MachOPlatform::MachOPlatformPlugin::registerInitSections( 720 jitlink::LinkGraph &G, JITDylib &JD) { 721 722 SmallVector<jitlink::Section *> InitSections; 723 724 for (auto InitSectionName : InitSectionNames) 725 if (auto *Sec = G.findSectionByName(InitSectionName)) 726 InitSections.push_back(Sec); 727 728 // Dump the scraped inits. 729 LLVM_DEBUG({ 730 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 731 for (auto *Sec : InitSections) { 732 jitlink::SectionRange R(*Sec); 733 dbgs() << " " << Sec->getName() << ": " 734 << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; 735 } 736 }); 737 738 return MP.registerInitInfo(JD, InitSections); 739 } 740 741 } // End namespace orc. 742 } // End namespace llvm. 743