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 // FIXME: Proper mangling. 450 auto MangledName = ("_" + SymbolName).str(); 451 ES.lookup( 452 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 453 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, 454 [SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable { 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 NoDependenciesToRegister); 462 } 463 464 Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) { 465 466 std::pair<const char *, ExecutorAddress *> Symbols[] = { 467 {"___orc_rt_macho_platform_bootstrap", &orc_rt_macho_platform_bootstrap}, 468 {"___orc_rt_macho_platform_shutdown", &orc_rt_macho_platform_shutdown}, 469 {"___orc_rt_macho_register_object_sections", 470 &orc_rt_macho_register_object_sections}}; 471 472 SymbolLookupSet RuntimeSymbols; 473 std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> AddrsToRecord; 474 for (const auto &KV : Symbols) { 475 auto Name = ES.intern(KV.first); 476 RuntimeSymbols.add(Name); 477 AddrsToRecord.push_back({std::move(Name), KV.second}); 478 } 479 480 auto RuntimeSymbolAddrs = ES.lookup( 481 {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols); 482 if (!RuntimeSymbolAddrs) 483 return RuntimeSymbolAddrs.takeError(); 484 485 for (const auto &KV : AddrsToRecord) { 486 auto &Name = KV.first; 487 assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?"); 488 KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress()); 489 } 490 491 if (auto Err = 492 EPC.runSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue())) 493 return Err; 494 495 // FIXME: Ordering is fuzzy here. We're probably best off saying 496 // "behavior is undefined if code that uses the runtime is added before 497 // the platform constructor returns", then move all this to the constructor. 498 RuntimeBootstrapped = true; 499 std::vector<MachOPerObjectSectionsToRegister> DeferredPOSRs; 500 { 501 std::lock_guard<std::mutex> Lock(PlatformMutex); 502 DeferredPOSRs = std::move(BootstrapPOSRs); 503 } 504 505 for (auto &D : DeferredPOSRs) 506 if (auto Err = registerPerObjectSections(D)) 507 return Err; 508 509 return Error::success(); 510 } 511 512 Error MachOPlatform::registerInitInfo( 513 JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) { 514 515 std::unique_lock<std::mutex> Lock(PlatformMutex); 516 517 MachOJITDylibInitializers *InitSeq = nullptr; 518 { 519 auto I = InitSeqs.find(&JD); 520 if (I == InitSeqs.end()) { 521 // If there's no init sequence entry yet then we need to look up the 522 // header symbol to force creation of one. 523 Lock.unlock(); 524 525 auto SearchOrder = 526 JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); 527 if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError()) 528 return Err; 529 530 Lock.lock(); 531 I = InitSeqs.find(&JD); 532 assert(I != InitSeqs.end() && 533 "Entry missing after header symbol lookup?"); 534 } 535 InitSeq = &I->second; 536 } 537 538 for (auto *Sec : InitSections) { 539 // FIXME: Avoid copy here. 540 jitlink::SectionRange R(*Sec); 541 InitSeq->InitSections[Sec->getName()].push_back( 542 {ExecutorAddress(R.getStart()), ExecutorAddress(R.getEnd())}); 543 } 544 545 return Error::success(); 546 } 547 548 Error MachOPlatform::registerPerObjectSections( 549 const MachOPerObjectSectionsToRegister &POSR) { 550 551 if (!orc_rt_macho_register_object_sections) 552 return make_error<StringError>("Attempting to register per-object " 553 "sections, but runtime support has not " 554 "been loaded yet", 555 inconvertibleErrorCode()); 556 557 Error ErrResult = Error::success(); 558 if (auto Err = EPC.runSPSWrapper<shared::SPSError( 559 SPSMachOPerObjectSectionsToRegister)>( 560 orc_rt_macho_register_object_sections.getValue(), ErrResult, POSR)) 561 return Err; 562 return ErrResult; 563 } 564 565 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 566 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 567 jitlink::PassConfiguration &Config) { 568 569 // If the initializer symbol is the MachOHeader start symbol then just add 570 // the macho header support passes. 571 if (MR.getInitializerSymbol() == MP.MachOHeaderStartSymbol) { 572 addMachOHeaderSupportPasses(MR, Config); 573 // The header materialization unit doesn't require any other support, so we 574 // can bail out early. 575 return; 576 } 577 578 // If the object contains initializers then add passes to record them. 579 if (MR.getInitializerSymbol()) 580 addInitializerSupportPasses(MR, Config); 581 582 // Add passes for eh-frame support. 583 addEHSupportPasses(MR, Config); 584 } 585 586 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 587 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 588 MaterializationResponsibility &MR) { 589 std::lock_guard<std::mutex> Lock(PluginMutex); 590 auto I = InitSymbolDeps.find(&MR); 591 if (I != InitSymbolDeps.end()) { 592 SyntheticSymbolDependenciesMap Result; 593 Result[MR.getInitializerSymbol()] = std::move(I->second); 594 InitSymbolDeps.erase(&MR); 595 return Result; 596 } 597 return SyntheticSymbolDependenciesMap(); 598 } 599 600 void MachOPlatform::MachOPlatformPlugin::addInitializerSupportPasses( 601 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 602 603 /// Preserve init sections. 604 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { 605 return preserveInitSections(G, MR); 606 }); 607 608 Config.PostFixupPasses.push_back( 609 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 610 return registerInitSections(G, JD); 611 }); 612 } 613 614 void MachOPlatform::MachOPlatformPlugin::addMachOHeaderSupportPasses( 615 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 616 617 Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()]( 618 jitlink::LinkGraph &G) -> Error { 619 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 620 return Sym->getName() == *MP.MachOHeaderStartSymbol; 621 }); 622 assert(I != G.defined_symbols().end() && 623 "Missing MachO header start symbol"); 624 { 625 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 626 JITTargetAddress HeaderAddr = (*I)->getAddress(); 627 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 628 assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); 629 MP.InitSeqs.insert( 630 std::make_pair(&JD, MachOJITDylibInitializers( 631 JD.getName(), ExecutorAddress(HeaderAddr)))); 632 } 633 return Error::success(); 634 }); 635 } 636 637 void MachOPlatform::MachOPlatformPlugin::addEHSupportPasses( 638 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 639 640 // Add a pass to register the final addresses of the eh-frame sections 641 // with the runtime. 642 Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { 643 MachOPerObjectSectionsToRegister POSR; 644 645 if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { 646 jitlink::SectionRange R(*EHFrameSection); 647 if (!R.empty()) 648 POSR.EHFrameSection = {ExecutorAddress(R.getStart()), 649 ExecutorAddress(R.getEnd())}; 650 } 651 652 if (POSR.EHFrameSection.StartAddress) { 653 654 // If we're still bootstrapping the runtime then just record this 655 // frame for now. 656 if (!MP.RuntimeBootstrapped) { 657 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 658 MP.BootstrapPOSRs.push_back(POSR); 659 return Error::success(); 660 } 661 662 // Otherwise register it immediately. 663 if (auto Err = MP.registerPerObjectSections(POSR)) 664 return Err; 665 } 666 667 return Error::success(); 668 }); 669 } 670 671 Error MachOPlatform::MachOPlatformPlugin::preserveInitSections( 672 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 673 674 JITLinkSymbolSet InitSectionSymbols; 675 for (auto &InitSectionName : InitSectionNames) { 676 // Skip non-init sections. 677 auto *InitSection = G.findSectionByName(InitSectionName); 678 if (!InitSection) 679 continue; 680 681 // Make a pass over live symbols in the section: those blocks are already 682 // preserved. 683 DenseSet<jitlink::Block *> AlreadyLiveBlocks; 684 for (auto &Sym : InitSection->symbols()) { 685 auto &B = Sym->getBlock(); 686 if (Sym->isLive() && Sym->getOffset() == 0 && 687 Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 688 InitSectionSymbols.insert(Sym); 689 AlreadyLiveBlocks.insert(&B); 690 } 691 } 692 693 // Add anonymous symbols to preserve any not-already-preserved blocks. 694 for (auto *B : InitSection->blocks()) 695 if (!AlreadyLiveBlocks.count(B)) 696 InitSectionSymbols.insert( 697 &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 698 } 699 700 if (!InitSectionSymbols.empty()) { 701 std::lock_guard<std::mutex> Lock(PluginMutex); 702 InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 703 } 704 705 return Error::success(); 706 } 707 708 Error MachOPlatform::MachOPlatformPlugin::registerInitSections( 709 jitlink::LinkGraph &G, JITDylib &JD) { 710 711 SmallVector<jitlink::Section *> InitSections; 712 713 for (auto InitSectionName : InitSectionNames) 714 if (auto *Sec = G.findSectionByName(InitSectionName)) 715 InitSections.push_back(Sec); 716 717 // Dump the scraped inits. 718 LLVM_DEBUG({ 719 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 720 for (auto *Sec : InitSections) { 721 jitlink::SectionRange R(*Sec); 722 dbgs() << " " << Sec->getName() << ": " 723 << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; 724 } 725 }); 726 727 return MP.registerInitInfo(JD, InitSections); 728 } 729 730 } // End namespace orc. 731 } // End namespace llvm. 732