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