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