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