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/ExecutionEngine/Orc/LookupAndRecordAddrs.h" 16 #include "llvm/Support/BinaryByteStream.h" 17 #include "llvm/Support/Debug.h" 18 19 #define DEBUG_TYPE "orc" 20 21 using namespace llvm; 22 using namespace llvm::orc; 23 using namespace llvm::orc::shared; 24 25 namespace { 26 27 class MachOHeaderMaterializationUnit : public MaterializationUnit { 28 public: 29 MachOHeaderMaterializationUnit(MachOPlatform &MOP, 30 const SymbolStringPtr &HeaderStartSymbol) 31 : MaterializationUnit(createHeaderSymbols(MOP, HeaderStartSymbol), 32 HeaderStartSymbol), 33 MOP(MOP) {} 34 35 StringRef getName() const override { return "MachOHeaderMU"; } 36 37 void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 38 unsigned PointerSize; 39 support::endianness Endianness; 40 const auto &TT = 41 MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple(); 42 43 switch (TT.getArch()) { 44 case Triple::aarch64: 45 case Triple::x86_64: 46 PointerSize = 8; 47 Endianness = support::endianness::little; 48 break; 49 default: 50 llvm_unreachable("Unrecognized architecture"); 51 } 52 53 auto G = std::make_unique<jitlink::LinkGraph>( 54 "<MachOHeaderMU>", TT, PointerSize, Endianness, 55 jitlink::getGenericEdgeKindName); 56 auto &HeaderSection = G->createSection("__header", jitlink::MemProt::Read); 57 auto &HeaderBlock = createHeaderBlock(*G, HeaderSection); 58 59 // Init symbol is header-start symbol. 60 G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(), 61 HeaderBlock.getSize(), jitlink::Linkage::Strong, 62 jitlink::Scope::Default, false, true); 63 for (auto &HS : AdditionalHeaderSymbols) 64 G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, 65 HeaderBlock.getSize(), jitlink::Linkage::Strong, 66 jitlink::Scope::Default, false, true); 67 68 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 69 } 70 71 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 72 73 private: 74 struct HeaderSymbol { 75 const char *Name; 76 uint64_t Offset; 77 }; 78 79 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = { 80 {"___mh_executable_header", 0}}; 81 82 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G, 83 jitlink::Section &HeaderSection) { 84 MachO::mach_header_64 Hdr; 85 Hdr.magic = MachO::MH_MAGIC_64; 86 switch (G.getTargetTriple().getArch()) { 87 case Triple::aarch64: 88 Hdr.cputype = MachO::CPU_TYPE_ARM64; 89 Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 90 break; 91 case Triple::x86_64: 92 Hdr.cputype = MachO::CPU_TYPE_X86_64; 93 Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 94 break; 95 default: 96 llvm_unreachable("Unrecognized architecture"); 97 } 98 Hdr.filetype = MachO::MH_DYLIB; // Custom file type? 99 Hdr.ncmds = 0; 100 Hdr.sizeofcmds = 0; 101 Hdr.flags = 0; 102 Hdr.reserved = 0; 103 104 if (G.getEndianness() != support::endian::system_endianness()) 105 MachO::swapStruct(Hdr); 106 107 auto HeaderContent = G.allocateString( 108 StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr))); 109 110 return G.createContentBlock(HeaderSection, HeaderContent, 0, 8, 0); 111 } 112 113 static SymbolFlagsMap 114 createHeaderSymbols(MachOPlatform &MOP, 115 const SymbolStringPtr &HeaderStartSymbol) { 116 SymbolFlagsMap HeaderSymbolFlags; 117 118 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 119 for (auto &HS : AdditionalHeaderSymbols) 120 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = 121 JITSymbolFlags::Exported; 122 123 return HeaderSymbolFlags; 124 } 125 126 MachOPlatform &MOP; 127 }; 128 129 constexpr MachOHeaderMaterializationUnit::HeaderSymbol 130 MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[]; 131 132 StringRef EHFrameSectionName = "__TEXT,__eh_frame"; 133 StringRef ModInitFuncSectionName = "__DATA,__mod_init_func"; 134 StringRef ObjCClassListSectionName = "__DATA,__objc_classlist"; 135 StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info"; 136 StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs"; 137 StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto"; 138 StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos"; 139 StringRef ThreadBSSSectionName = "__DATA,__thread_bss"; 140 StringRef ThreadDataSectionName = "__DATA,__thread_data"; 141 StringRef ThreadVarsSectionName = "__DATA,__thread_vars"; 142 143 StringRef InitSectionNames[] = { 144 ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName, 145 Swift5ProtosSectionName, Swift5ProtoSectionName}; 146 147 } // end anonymous namespace 148 149 namespace llvm { 150 namespace orc { 151 152 Expected<std::unique_ptr<MachOPlatform>> 153 MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 154 JITDylib &PlatformJD, const char *OrcRuntimePath, 155 Optional<SymbolAliasMap> RuntimeAliases) { 156 157 auto &EPC = ES.getExecutorProcessControl(); 158 159 // If the target is not supported then bail out immediately. 160 if (!supportedTarget(EPC.getTargetTriple())) 161 return make_error<StringError>("Unsupported MachOPlatform triple: " + 162 EPC.getTargetTriple().str(), 163 inconvertibleErrorCode()); 164 165 // Create default aliases if the caller didn't supply any. 166 if (!RuntimeAliases) 167 RuntimeAliases = standardPlatformAliases(ES); 168 169 // Define the aliases. 170 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 171 return std::move(Err); 172 173 // Add JIT-dispatch function support symbols. 174 if (auto Err = PlatformJD.define(absoluteSymbols( 175 {{ES.intern("___orc_rt_jit_dispatch"), 176 {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(), 177 JITSymbolFlags::Exported}}, 178 {ES.intern("___orc_rt_jit_dispatch_ctx"), 179 {EPC.getJITDispatchInfo().JITDispatchContext.getValue(), 180 JITSymbolFlags::Exported}}}))) 181 return std::move(Err); 182 183 // Create a generator for the ORC runtime archive. 184 auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load( 185 ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple()); 186 if (!OrcRuntimeArchiveGenerator) 187 return OrcRuntimeArchiveGenerator.takeError(); 188 189 // Create the instance. 190 Error Err = Error::success(); 191 auto P = std::unique_ptr<MachOPlatform>( 192 new MachOPlatform(ES, ObjLinkingLayer, PlatformJD, 193 std::move(*OrcRuntimeArchiveGenerator), Err)); 194 if (Err) 195 return std::move(Err); 196 return std::move(P); 197 } 198 199 Error MachOPlatform::setupJITDylib(JITDylib &JD) { 200 return JD.define(std::make_unique<MachOHeaderMaterializationUnit>( 201 *this, MachOHeaderStartSymbol)); 202 } 203 204 Error MachOPlatform::notifyAdding(ResourceTracker &RT, 205 const MaterializationUnit &MU) { 206 auto &JD = RT.getJITDylib(); 207 const auto &InitSym = MU.getInitializerSymbol(); 208 if (!InitSym) 209 return Error::success(); 210 211 RegisteredInitSymbols[&JD].add(InitSym, 212 SymbolLookupFlags::WeaklyReferencedSymbol); 213 LLVM_DEBUG({ 214 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU " 215 << MU.getName() << "\n"; 216 }); 217 return Error::success(); 218 } 219 220 Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { 221 llvm_unreachable("Not supported yet"); 222 } 223 224 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 225 ArrayRef<std::pair<const char *, const char *>> AL) { 226 for (auto &KV : AL) { 227 auto AliasName = ES.intern(KV.first); 228 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 229 Aliases[std::move(AliasName)] = {ES.intern(KV.second), 230 JITSymbolFlags::Exported}; 231 } 232 } 233 234 SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { 235 SymbolAliasMap Aliases; 236 addAliases(ES, Aliases, requiredCXXAliases()); 237 addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 238 return Aliases; 239 } 240 241 ArrayRef<std::pair<const char *, const char *>> 242 MachOPlatform::requiredCXXAliases() { 243 static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 244 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; 245 246 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 247 } 248 249 ArrayRef<std::pair<const char *, const char *>> 250 MachOPlatform::standardRuntimeUtilityAliases() { 251 static const std::pair<const char *, const char *> 252 StandardRuntimeUtilityAliases[] = { 253 {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, 254 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; 255 256 return ArrayRef<std::pair<const char *, const char *>>( 257 StandardRuntimeUtilityAliases); 258 } 259 260 bool MachOPlatform::isInitializerSection(StringRef SegName, 261 StringRef SectName) { 262 for (auto &Name : InitSectionNames) { 263 if (Name.startswith(SegName) && Name.substr(7) == SectName) 264 return true; 265 } 266 return false; 267 } 268 269 bool MachOPlatform::supportedTarget(const Triple &TT) { 270 switch (TT.getArch()) { 271 case Triple::aarch64: 272 case Triple::x86_64: 273 return true; 274 default: 275 return false; 276 } 277 } 278 279 MachOPlatform::MachOPlatform( 280 ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 281 JITDylib &PlatformJD, 282 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err) 283 : ES(ES), ObjLinkingLayer(ObjLinkingLayer), 284 MachOHeaderStartSymbol(ES.intern("___dso_handle")) { 285 ErrorAsOutParameter _(&Err); 286 287 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this)); 288 289 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 290 291 // Force linking of eh-frame registration functions. 292 if (auto Err2 = lookupAndRecordAddrs( 293 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD), 294 {{ES.intern("___orc_rt_macho_register_ehframe_section"), 295 &orc_rt_macho_register_ehframe_section}, 296 {ES.intern("___orc_rt_macho_deregister_ehframe_section"), 297 &orc_rt_macho_deregister_ehframe_section}})) { 298 Err = std::move(Err2); 299 return; 300 } 301 302 State = BootstrapPhase2; 303 304 // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating 305 // the platform now), so set it up. 306 if (auto E2 = setupJITDylib(PlatformJD)) { 307 Err = std::move(E2); 308 return; 309 } 310 311 RegisteredInitSymbols[&PlatformJD].add( 312 MachOHeaderStartSymbol, SymbolLookupFlags::WeaklyReferencedSymbol); 313 314 // Associate wrapper function tags with JIT-side function implementations. 315 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) { 316 Err = std::move(E2); 317 return; 318 } 319 320 // Lookup addresses of runtime functions callable by the platform, 321 // call the platform bootstrap function to initialize the platform-state 322 // object in the executor. 323 if (auto E2 = bootstrapMachORuntime(PlatformJD)) { 324 Err = std::move(E2); 325 return; 326 } 327 328 State = Initialized; 329 } 330 331 Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) { 332 ExecutionSession::JITDispatchHandlerAssociationMap WFs; 333 334 using GetInitializersSPSSig = 335 SPSExpected<SPSMachOJITDylibInitializerSequence>(SPSString); 336 WFs[ES.intern("___orc_rt_macho_get_initializers_tag")] = 337 ES.wrapAsyncWithSPS<GetInitializersSPSSig>( 338 this, &MachOPlatform::rt_getInitializers); 339 340 using GetDeinitializersSPSSig = 341 SPSExpected<SPSMachOJITDylibDeinitializerSequence>(SPSExecutorAddr); 342 WFs[ES.intern("___orc_rt_macho_get_deinitializers_tag")] = 343 ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>( 344 this, &MachOPlatform::rt_getDeinitializers); 345 346 using LookupSymbolSPSSig = 347 SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString); 348 WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] = 349 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this, 350 &MachOPlatform::rt_lookupSymbol); 351 352 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 353 } 354 355 void MachOPlatform::getInitializersBuildSequencePhase( 356 SendInitializerSequenceFn SendResult, JITDylib &JD, 357 std::vector<JITDylibSP> DFSLinkOrder) { 358 MachOJITDylibInitializerSequence FullInitSeq; 359 { 360 std::lock_guard<std::mutex> Lock(PlatformMutex); 361 for (auto &InitJD : reverse(DFSLinkOrder)) { 362 LLVM_DEBUG({ 363 dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName() 364 << "\" to sequence\n"; 365 }); 366 auto ISItr = InitSeqs.find(InitJD.get()); 367 if (ISItr != InitSeqs.end()) { 368 FullInitSeq.emplace_back(std::move(ISItr->second)); 369 InitSeqs.erase(ISItr); 370 } 371 } 372 } 373 374 SendResult(std::move(FullInitSeq)); 375 } 376 377 void MachOPlatform::getInitializersLookupPhase( 378 SendInitializerSequenceFn SendResult, JITDylib &JD) { 379 380 auto DFSLinkOrder = JD.getDFSLinkOrder(); 381 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 382 ES.runSessionLocked([&]() { 383 for (auto &InitJD : DFSLinkOrder) { 384 auto RISItr = RegisteredInitSymbols.find(InitJD.get()); 385 if (RISItr != RegisteredInitSymbols.end()) { 386 NewInitSymbols[InitJD.get()] = std::move(RISItr->second); 387 RegisteredInitSymbols.erase(RISItr); 388 } 389 } 390 }); 391 392 // If there are no further init symbols to look up then move on to the next 393 // phase. 394 if (NewInitSymbols.empty()) { 395 getInitializersBuildSequencePhase(std::move(SendResult), JD, 396 std::move(DFSLinkOrder)); 397 return; 398 } 399 400 // Otherwise issue a lookup and re-run this phase when it completes. 401 lookupInitSymbolsAsync( 402 [this, SendResult = std::move(SendResult), &JD](Error Err) mutable { 403 if (Err) 404 SendResult(std::move(Err)); 405 else 406 getInitializersLookupPhase(std::move(SendResult), JD); 407 }, 408 ES, std::move(NewInitSymbols)); 409 } 410 411 void MachOPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult, 412 StringRef JDName) { 413 LLVM_DEBUG({ 414 dbgs() << "MachOPlatform::rt_getInitializers(\"" << JDName << "\")\n"; 415 }); 416 417 JITDylib *JD = ES.getJITDylibByName(JDName); 418 if (!JD) { 419 LLVM_DEBUG({ 420 dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n"; 421 }); 422 SendResult(make_error<StringError>("No JITDylib named " + JDName, 423 inconvertibleErrorCode())); 424 return; 425 } 426 427 getInitializersLookupPhase(std::move(SendResult), *JD); 428 } 429 430 void MachOPlatform::rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, 431 ExecutorAddr Handle) { 432 LLVM_DEBUG({ 433 dbgs() << "MachOPlatform::rt_getDeinitializers(\"" 434 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 435 }); 436 437 JITDylib *JD = nullptr; 438 439 { 440 std::lock_guard<std::mutex> Lock(PlatformMutex); 441 auto I = HeaderAddrToJITDylib.find(Handle.getValue()); 442 if (I != HeaderAddrToJITDylib.end()) 443 JD = I->second; 444 } 445 446 if (!JD) { 447 LLVM_DEBUG({ 448 dbgs() << " No JITDylib for handle " 449 << formatv("{0:x}", Handle.getValue()) << "\n"; 450 }); 451 SendResult(make_error<StringError>("No JITDylib associated with handle " + 452 formatv("{0:x}", Handle.getValue()), 453 inconvertibleErrorCode())); 454 return; 455 } 456 457 SendResult(MachOJITDylibDeinitializerSequence()); 458 } 459 460 void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 461 ExecutorAddr Handle, StringRef SymbolName) { 462 LLVM_DEBUG({ 463 dbgs() << "MachOPlatform::rt_lookupSymbol(\"" 464 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 465 }); 466 467 JITDylib *JD = nullptr; 468 469 { 470 std::lock_guard<std::mutex> Lock(PlatformMutex); 471 auto I = HeaderAddrToJITDylib.find(Handle.getValue()); 472 if (I != HeaderAddrToJITDylib.end()) 473 JD = I->second; 474 } 475 476 if (!JD) { 477 LLVM_DEBUG({ 478 dbgs() << " No JITDylib for handle " 479 << formatv("{0:x}", Handle.getValue()) << "\n"; 480 }); 481 SendResult(make_error<StringError>("No JITDylib associated with handle " + 482 formatv("{0:x}", Handle.getValue()), 483 inconvertibleErrorCode())); 484 return; 485 } 486 487 // Use functor class to work around XL build compiler issue on AIX. 488 class RtLookupNotifyComplete { 489 public: 490 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 491 : SendResult(std::move(SendResult)) {} 492 void operator()(Expected<SymbolMap> Result) { 493 if (Result) { 494 assert(Result->size() == 1 && "Unexpected result map count"); 495 SendResult(ExecutorAddr(Result->begin()->second.getAddress())); 496 } else { 497 SendResult(Result.takeError()); 498 } 499 } 500 501 private: 502 SendSymbolAddressFn SendResult; 503 }; 504 505 // FIXME: Proper mangling. 506 auto MangledName = ("_" + SymbolName).str(); 507 ES.lookup( 508 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 509 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, 510 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 511 } 512 513 Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) { 514 if (auto Err = lookupAndRecordAddrs( 515 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD), 516 {{ES.intern("___orc_rt_macho_platform_bootstrap"), 517 &orc_rt_macho_platform_bootstrap}, 518 {ES.intern("___orc_rt_macho_platform_shutdown"), 519 &orc_rt_macho_platform_shutdown}, 520 {ES.intern("___orc_rt_macho_register_thread_data_section"), 521 &orc_rt_macho_register_thread_data_section}, 522 {ES.intern("___orc_rt_macho_deregister_thread_data_section"), 523 &orc_rt_macho_deregister_thread_data_section}, 524 {ES.intern("___orc_rt_macho_create_pthread_key"), 525 &orc_rt_macho_create_pthread_key}})) 526 return Err; 527 528 return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap); 529 } 530 531 Error MachOPlatform::registerInitInfo( 532 JITDylib &JD, ExecutorAddr ObjCImageInfoAddr, 533 ArrayRef<jitlink::Section *> InitSections) { 534 535 std::unique_lock<std::mutex> Lock(PlatformMutex); 536 537 MachOJITDylibInitializers *InitSeq = nullptr; 538 { 539 auto I = InitSeqs.find(&JD); 540 if (I == InitSeqs.end()) { 541 // If there's no init sequence entry yet then we need to look up the 542 // header symbol to force creation of one. 543 Lock.unlock(); 544 545 auto SearchOrder = 546 JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); 547 if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError()) 548 return Err; 549 550 Lock.lock(); 551 I = InitSeqs.find(&JD); 552 assert(I != InitSeqs.end() && 553 "Entry missing after header symbol lookup?"); 554 } 555 InitSeq = &I->second; 556 } 557 558 InitSeq->ObjCImageInfoAddress = ObjCImageInfoAddr; 559 560 for (auto *Sec : InitSections) { 561 // FIXME: Avoid copy here. 562 jitlink::SectionRange R(*Sec); 563 InitSeq->InitSections[Sec->getName()].push_back( 564 {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())}); 565 } 566 567 return Error::success(); 568 } 569 570 Expected<uint64_t> MachOPlatform::createPThreadKey() { 571 if (!orc_rt_macho_create_pthread_key) 572 return make_error<StringError>( 573 "Attempting to create pthread key in target, but runtime support has " 574 "not been loaded yet", 575 inconvertibleErrorCode()); 576 577 Expected<uint64_t> Result(0); 578 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 579 orc_rt_macho_create_pthread_key, Result)) 580 return std::move(Err); 581 return Result; 582 } 583 584 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 585 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 586 jitlink::PassConfiguration &Config) { 587 588 auto PS = MP.State.load(); 589 590 // --- Handle Initializers --- 591 if (auto InitSymbol = MR.getInitializerSymbol()) { 592 593 // If the initializer symbol is the MachOHeader start symbol then just 594 // register it and then bail out -- the header materialization unit 595 // definitely doesn't need any other passes. 596 if (InitSymbol == MP.MachOHeaderStartSymbol) { 597 Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) { 598 return associateJITDylibHeaderSymbol(G, MR); 599 }); 600 return; 601 } 602 603 // If the object contains an init symbol other than the header start symbol 604 // then add passes to preserve, process and register the init 605 // sections/symbols. 606 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { 607 if (auto Err = preserveInitSections(G, MR)) 608 return Err; 609 return processObjCImageInfo(G, MR); 610 }); 611 612 Config.PostFixupPasses.push_back( 613 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 614 return registerInitSections(G, JD); 615 }); 616 } 617 618 // --- Add passes for eh-frame and TLV support --- 619 if (PS == MachOPlatform::BootstrapPhase1) { 620 Config.PostFixupPasses.push_back( 621 [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); }); 622 return; 623 } 624 625 // Insert TLV lowering at the start of the PostPrunePasses, since we want 626 // it to run before GOT/PLT lowering. 627 Config.PostPrunePasses.insert( 628 Config.PostPrunePasses.begin(), 629 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 630 return fixTLVSectionsAndEdges(G, JD); 631 }); 632 633 // Add a pass to register the final addresses of the eh-frame and TLV sections 634 // with the runtime. 635 Config.PostFixupPasses.push_back( 636 [this](jitlink::LinkGraph &G) { return registerEHAndTLVSections(G); }); 637 } 638 639 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 640 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 641 MaterializationResponsibility &MR) { 642 std::lock_guard<std::mutex> Lock(PluginMutex); 643 auto I = InitSymbolDeps.find(&MR); 644 if (I != InitSymbolDeps.end()) { 645 SyntheticSymbolDependenciesMap Result; 646 Result[MR.getInitializerSymbol()] = std::move(I->second); 647 InitSymbolDeps.erase(&MR); 648 return Result; 649 } 650 return SyntheticSymbolDependenciesMap(); 651 } 652 653 Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol( 654 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 655 656 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 657 return Sym->getName() == *MP.MachOHeaderStartSymbol; 658 }); 659 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol"); 660 661 auto &JD = MR.getTargetJITDylib(); 662 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 663 JITTargetAddress HeaderAddr = (*I)->getAddress(); 664 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 665 assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); 666 MP.InitSeqs.insert(std::make_pair( 667 &JD, MachOJITDylibInitializers(JD.getName(), ExecutorAddr(HeaderAddr)))); 668 return Error::success(); 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::processObjCImageInfo( 709 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 710 711 // If there's an ObjC imagine info then either 712 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In 713 // this case we name and record it. 714 // OR 715 // (2) We already have a recorded __objc_imageinfo for this JITDylib, 716 // in which case we just verify it. 717 auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName); 718 if (!ObjCImageInfo) 719 return Error::success(); 720 721 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); 722 723 // Check that the section is not empty if present. 724 if (llvm::empty(ObjCImageInfoBlocks)) 725 return make_error<StringError>("Empty " + ObjCImageInfoSectionName + 726 " section in " + G.getName(), 727 inconvertibleErrorCode()); 728 729 // Check that there's only one block in the section. 730 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) 731 return make_error<StringError>("Multiple blocks in " + 732 ObjCImageInfoSectionName + 733 " section in " + G.getName(), 734 inconvertibleErrorCode()); 735 736 // Check that the __objc_imageinfo section is unreferenced. 737 // FIXME: We could optimize this check if Symbols had a ref-count. 738 for (auto &Sec : G.sections()) { 739 if (&Sec != ObjCImageInfo) 740 for (auto *B : Sec.blocks()) 741 for (auto &E : B->edges()) 742 if (E.getTarget().isDefined() && 743 &E.getTarget().getBlock().getSection() == ObjCImageInfo) 744 return make_error<StringError>(ObjCImageInfoSectionName + 745 " is referenced within file " + 746 G.getName(), 747 inconvertibleErrorCode()); 748 } 749 750 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); 751 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); 752 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); 753 auto Flags = 754 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); 755 756 // Lock the mutex while we verify / update the ObjCImageInfos map. 757 std::lock_guard<std::mutex> Lock(PluginMutex); 758 759 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); 760 if (ObjCImageInfoItr != ObjCImageInfos.end()) { 761 // We've already registered an __objc_imageinfo section. Verify the 762 // content of this new section matches, then delete it. 763 if (ObjCImageInfoItr->second.first != Version) 764 return make_error<StringError>( 765 "ObjC version in " + G.getName() + 766 " does not match first registered version", 767 inconvertibleErrorCode()); 768 if (ObjCImageInfoItr->second.second != Flags) 769 return make_error<StringError>("ObjC flags in " + G.getName() + 770 " do not match first registered flags", 771 inconvertibleErrorCode()); 772 773 // __objc_imageinfo is valid. Delete the block. 774 for (auto *S : ObjCImageInfo->symbols()) 775 G.removeDefinedSymbol(*S); 776 G.removeBlock(ObjCImageInfoBlock); 777 } else { 778 // We haven't registered an __objc_imageinfo section yet. Register and 779 // move on. The section should already be marked no-dead-strip. 780 ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags); 781 } 782 783 return Error::success(); 784 } 785 786 Error MachOPlatform::MachOPlatformPlugin::registerInitSections( 787 jitlink::LinkGraph &G, JITDylib &JD) { 788 789 ExecutorAddr ObjCImageInfoAddr; 790 SmallVector<jitlink::Section *> InitSections; 791 792 if (auto *ObjCImageInfoSec = G.findSectionByName(ObjCImageInfoSectionName)) { 793 if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) 794 ObjCImageInfoAddr.setValue(Addr); 795 } 796 797 for (auto InitSectionName : InitSectionNames) 798 if (auto *Sec = G.findSectionByName(InitSectionName)) 799 InitSections.push_back(Sec); 800 801 // Dump the scraped inits. 802 LLVM_DEBUG({ 803 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 804 if (ObjCImageInfoAddr) 805 dbgs() << " " << ObjCImageInfoSectionName << ": " 806 << formatv("{0:x}", ObjCImageInfoAddr.getValue()) << "\n"; 807 for (auto *Sec : InitSections) { 808 jitlink::SectionRange R(*Sec); 809 dbgs() << " " << Sec->getName() << ": " 810 << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; 811 } 812 }); 813 814 return MP.registerInitInfo(JD, ObjCImageInfoAddr, InitSections); 815 } 816 817 Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges( 818 jitlink::LinkGraph &G, JITDylib &JD) { 819 820 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr. 821 for (auto *Sym : G.external_symbols()) 822 if (Sym->getName() == "__tlv_bootstrap") { 823 Sym->setName("___orc_rt_macho_tlv_get_addr"); 824 break; 825 } 826 827 // Store key in __thread_vars struct fields. 828 if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) { 829 Optional<uint64_t> Key; 830 { 831 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 832 auto I = MP.JITDylibToPThreadKey.find(&JD); 833 if (I != MP.JITDylibToPThreadKey.end()) 834 Key = I->second; 835 } 836 837 if (!Key) { 838 if (auto KeyOrErr = MP.createPThreadKey()) 839 Key = *KeyOrErr; 840 else 841 return KeyOrErr.takeError(); 842 } 843 844 uint64_t PlatformKeyBits = 845 support::endian::byte_swap(*Key, G.getEndianness()); 846 847 for (auto *B : ThreadDataSec->blocks()) { 848 if (B->getSize() != 3 * G.getPointerSize()) 849 return make_error<StringError>("__thread_vars block at " + 850 formatv("{0:x}", B->getAddress()) + 851 " has unexpected size", 852 inconvertibleErrorCode()); 853 854 auto NewBlockContent = G.allocateBuffer(B->getSize()); 855 llvm::copy(B->getContent(), NewBlockContent.data()); 856 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits, 857 G.getPointerSize()); 858 B->setContent(NewBlockContent); 859 } 860 } 861 862 // Transform any TLV edges into GOT edges. 863 for (auto *B : G.blocks()) 864 for (auto &E : B->edges()) 865 if (E.getKind() == 866 jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable) 867 E.setKind(jitlink::x86_64:: 868 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable); 869 870 return Error::success(); 871 } 872 873 Error MachOPlatform::MachOPlatformPlugin::registerEHAndTLVSections( 874 jitlink::LinkGraph &G) { 875 876 // Add a pass to register the final addresses of the eh-frame and TLV sections 877 // with the runtime. 878 if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { 879 jitlink::SectionRange R(*EHFrameSection); 880 if (!R.empty()) 881 G.allocActions().push_back( 882 {{MP.orc_rt_macho_register_ehframe_section.getValue(), R.getStart(), 883 R.getSize()}, 884 {MP.orc_rt_macho_deregister_ehframe_section.getValue(), R.getStart(), 885 R.getSize()}}); 886 } 887 888 // Get a pointer to the thread data section if there is one. It will be used 889 // below. 890 jitlink::Section *ThreadDataSection = 891 G.findSectionByName(ThreadDataSectionName); 892 893 // Handle thread BSS section if there is one. 894 if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) { 895 // If there's already a thread data section in this graph then merge the 896 // thread BSS section content into it, otherwise just treat the thread 897 // BSS section as the thread data section. 898 if (ThreadDataSection) 899 G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 900 else 901 ThreadDataSection = ThreadBSSSection; 902 } 903 904 // Having merged thread BSS (if present) and thread data (if present), 905 // record the resulting section range. 906 if (ThreadDataSection) { 907 jitlink::SectionRange R(*ThreadDataSection); 908 if (!R.empty()) { 909 if (MP.State != MachOPlatform::Initialized) 910 return make_error<StringError>("__thread_data section encountered, but " 911 "MachOPlatform has not finished booting", 912 inconvertibleErrorCode()); 913 914 G.allocActions().push_back( 915 {{MP.orc_rt_macho_register_thread_data_section.getValue(), 916 R.getStart(), R.getSize()}, 917 {MP.orc_rt_macho_deregister_thread_data_section.getValue(), 918 R.getStart(), R.getSize()}}); 919 } 920 } 921 return Error::success(); 922 } 923 924 Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1( 925 jitlink::LinkGraph &G) { 926 927 // If there's no eh-frame there's nothing to do. 928 auto *EHFrameSection = G.findSectionByName(EHFrameSectionName); 929 if (!EHFrameSection) 930 return Error::success(); 931 932 // If the eh-frame section is empty there's nothing to do. 933 jitlink::SectionRange R(*EHFrameSection); 934 if (R.empty()) 935 return Error::success(); 936 937 // Since we're linking the object containing the registration code now the 938 // addresses won't be ready in the platform. We'll have to find them in this 939 // graph instead. 940 ExecutorAddr orc_rt_macho_register_ehframe_section; 941 ExecutorAddr orc_rt_macho_deregister_ehframe_section; 942 for (auto *Sym : G.defined_symbols()) { 943 if (!Sym->hasName()) 944 continue; 945 if (Sym->getName() == "___orc_rt_macho_register_ehframe_section") 946 orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress()); 947 else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section") 948 orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress()); 949 950 if (orc_rt_macho_register_ehframe_section && 951 orc_rt_macho_deregister_ehframe_section) 952 break; 953 } 954 955 // If we failed to find the required functions then bail out. 956 if (!orc_rt_macho_register_ehframe_section || 957 !orc_rt_macho_deregister_ehframe_section) 958 return make_error<StringError>("Could not find eh-frame registration " 959 "functions during platform bootstrap", 960 inconvertibleErrorCode()); 961 962 // Otherwise, add allocation actions to the graph to register eh-frames for 963 // this object. 964 G.allocActions().push_back( 965 {{orc_rt_macho_register_ehframe_section.getValue(), R.getStart(), 966 R.getSize()}, 967 {orc_rt_macho_deregister_ehframe_section.getValue(), R.getStart(), 968 R.getSize()}}); 969 970 return Error::success(); 971 } 972 973 } // End namespace orc. 974 } // End namespace llvm. 975