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 if (!DFSLinkOrder) { 386 SendResult(DFSLinkOrder.takeError()); 387 return; 388 } 389 390 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 391 ES.runSessionLocked([&]() { 392 for (auto &InitJD : *DFSLinkOrder) { 393 auto RISItr = RegisteredInitSymbols.find(InitJD.get()); 394 if (RISItr != RegisteredInitSymbols.end()) { 395 NewInitSymbols[InitJD.get()] = std::move(RISItr->second); 396 RegisteredInitSymbols.erase(RISItr); 397 } 398 } 399 }); 400 401 // If there are no further init symbols to look up then move on to the next 402 // phase. 403 if (NewInitSymbols.empty()) { 404 getInitializersBuildSequencePhase(std::move(SendResult), JD, 405 std::move(*DFSLinkOrder)); 406 return; 407 } 408 409 // Otherwise issue a lookup and re-run this phase when it completes. 410 lookupInitSymbolsAsync( 411 [this, SendResult = std::move(SendResult), &JD](Error Err) mutable { 412 if (Err) 413 SendResult(std::move(Err)); 414 else 415 getInitializersLookupPhase(std::move(SendResult), JD); 416 }, 417 ES, std::move(NewInitSymbols)); 418 } 419 420 void MachOPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult, 421 StringRef JDName) { 422 LLVM_DEBUG({ 423 dbgs() << "MachOPlatform::rt_getInitializers(\"" << JDName << "\")\n"; 424 }); 425 426 JITDylib *JD = ES.getJITDylibByName(JDName); 427 if (!JD) { 428 LLVM_DEBUG({ 429 dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n"; 430 }); 431 SendResult(make_error<StringError>("No JITDylib named " + JDName, 432 inconvertibleErrorCode())); 433 return; 434 } 435 436 getInitializersLookupPhase(std::move(SendResult), *JD); 437 } 438 439 void MachOPlatform::rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, 440 ExecutorAddr Handle) { 441 LLVM_DEBUG({ 442 dbgs() << "MachOPlatform::rt_getDeinitializers(\"" 443 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 444 }); 445 446 JITDylib *JD = nullptr; 447 448 { 449 std::lock_guard<std::mutex> Lock(PlatformMutex); 450 auto I = HeaderAddrToJITDylib.find(Handle); 451 if (I != HeaderAddrToJITDylib.end()) 452 JD = I->second; 453 } 454 455 if (!JD) { 456 LLVM_DEBUG({ 457 dbgs() << " No JITDylib for handle " 458 << formatv("{0:x}", Handle.getValue()) << "\n"; 459 }); 460 SendResult(make_error<StringError>("No JITDylib associated with handle " + 461 formatv("{0:x}", Handle.getValue()), 462 inconvertibleErrorCode())); 463 return; 464 } 465 466 SendResult(MachOJITDylibDeinitializerSequence()); 467 } 468 469 void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 470 ExecutorAddr Handle, StringRef SymbolName) { 471 LLVM_DEBUG({ 472 dbgs() << "MachOPlatform::rt_lookupSymbol(\"" 473 << formatv("{0:x}", Handle.getValue()) << "\")\n"; 474 }); 475 476 JITDylib *JD = nullptr; 477 478 { 479 std::lock_guard<std::mutex> Lock(PlatformMutex); 480 auto I = HeaderAddrToJITDylib.find(Handle); 481 if (I != HeaderAddrToJITDylib.end()) 482 JD = I->second; 483 } 484 485 if (!JD) { 486 LLVM_DEBUG({ 487 dbgs() << " No JITDylib for handle " 488 << formatv("{0:x}", Handle.getValue()) << "\n"; 489 }); 490 SendResult(make_error<StringError>("No JITDylib associated with handle " + 491 formatv("{0:x}", Handle.getValue()), 492 inconvertibleErrorCode())); 493 return; 494 } 495 496 // Use functor class to work around XL build compiler issue on AIX. 497 class RtLookupNotifyComplete { 498 public: 499 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 500 : SendResult(std::move(SendResult)) {} 501 void operator()(Expected<SymbolMap> Result) { 502 if (Result) { 503 assert(Result->size() == 1 && "Unexpected result map count"); 504 SendResult(ExecutorAddr(Result->begin()->second.getAddress())); 505 } else { 506 SendResult(Result.takeError()); 507 } 508 } 509 510 private: 511 SendSymbolAddressFn SendResult; 512 }; 513 514 // FIXME: Proper mangling. 515 auto MangledName = ("_" + SymbolName).str(); 516 ES.lookup( 517 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 518 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, 519 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 520 } 521 522 Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) { 523 if (auto Err = lookupAndRecordAddrs( 524 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD), 525 {{ES.intern("___orc_rt_macho_platform_bootstrap"), 526 &orc_rt_macho_platform_bootstrap}, 527 {ES.intern("___orc_rt_macho_platform_shutdown"), 528 &orc_rt_macho_platform_shutdown}, 529 {ES.intern("___orc_rt_macho_register_thread_data_section"), 530 &orc_rt_macho_register_thread_data_section}, 531 {ES.intern("___orc_rt_macho_deregister_thread_data_section"), 532 &orc_rt_macho_deregister_thread_data_section}, 533 {ES.intern("___orc_rt_macho_create_pthread_key"), 534 &orc_rt_macho_create_pthread_key}})) 535 return Err; 536 537 return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap); 538 } 539 540 Error MachOPlatform::registerInitInfo( 541 JITDylib &JD, ExecutorAddr ObjCImageInfoAddr, 542 ArrayRef<jitlink::Section *> InitSections) { 543 544 std::unique_lock<std::mutex> Lock(PlatformMutex); 545 546 MachOJITDylibInitializers *InitSeq = nullptr; 547 { 548 auto I = InitSeqs.find(&JD); 549 if (I == InitSeqs.end()) { 550 // If there's no init sequence entry yet then we need to look up the 551 // header symbol to force creation of one. 552 Lock.unlock(); 553 554 auto SearchOrder = 555 JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); 556 if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError()) 557 return Err; 558 559 Lock.lock(); 560 I = InitSeqs.find(&JD); 561 assert(I != InitSeqs.end() && 562 "Entry missing after header symbol lookup?"); 563 } 564 InitSeq = &I->second; 565 } 566 567 InitSeq->ObjCImageInfoAddress = ObjCImageInfoAddr; 568 569 for (auto *Sec : InitSections) { 570 // FIXME: Avoid copy here. 571 jitlink::SectionRange R(*Sec); 572 InitSeq->InitSections[Sec->getName()].push_back( 573 {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())}); 574 } 575 576 return Error::success(); 577 } 578 579 Expected<uint64_t> MachOPlatform::createPThreadKey() { 580 if (!orc_rt_macho_create_pthread_key) 581 return make_error<StringError>( 582 "Attempting to create pthread key in target, but runtime support has " 583 "not been loaded yet", 584 inconvertibleErrorCode()); 585 586 Expected<uint64_t> Result(0); 587 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 588 orc_rt_macho_create_pthread_key, Result)) 589 return std::move(Err); 590 return Result; 591 } 592 593 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 594 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 595 jitlink::PassConfiguration &Config) { 596 597 auto PS = MP.State.load(); 598 599 // --- Handle Initializers --- 600 if (auto InitSymbol = MR.getInitializerSymbol()) { 601 602 // If the initializer symbol is the MachOHeader start symbol then just 603 // register it and then bail out -- the header materialization unit 604 // definitely doesn't need any other passes. 605 if (InitSymbol == MP.MachOHeaderStartSymbol) { 606 Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) { 607 return associateJITDylibHeaderSymbol(G, MR); 608 }); 609 return; 610 } 611 612 // If the object contains an init symbol other than the header start symbol 613 // then add passes to preserve, process and register the init 614 // sections/symbols. 615 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { 616 if (auto Err = preserveInitSections(G, MR)) 617 return Err; 618 return processObjCImageInfo(G, MR); 619 }); 620 621 Config.PostFixupPasses.push_back( 622 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 623 return registerInitSections(G, JD); 624 }); 625 } 626 627 // --- Add passes for eh-frame and TLV support --- 628 if (PS == MachOPlatform::BootstrapPhase1) { 629 Config.PostFixupPasses.push_back( 630 [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); }); 631 return; 632 } 633 634 // Insert TLV lowering at the start of the PostPrunePasses, since we want 635 // it to run before GOT/PLT lowering. 636 Config.PostPrunePasses.insert( 637 Config.PostPrunePasses.begin(), 638 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 639 return fixTLVSectionsAndEdges(G, JD); 640 }); 641 642 // Add a pass to register the final addresses of the eh-frame and TLV sections 643 // with the runtime. 644 Config.PostFixupPasses.push_back( 645 [this](jitlink::LinkGraph &G) { return registerEHAndTLVSections(G); }); 646 } 647 648 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 649 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 650 MaterializationResponsibility &MR) { 651 std::lock_guard<std::mutex> Lock(PluginMutex); 652 auto I = InitSymbolDeps.find(&MR); 653 if (I != InitSymbolDeps.end()) { 654 SyntheticSymbolDependenciesMap Result; 655 Result[MR.getInitializerSymbol()] = std::move(I->second); 656 InitSymbolDeps.erase(&MR); 657 return Result; 658 } 659 return SyntheticSymbolDependenciesMap(); 660 } 661 662 Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol( 663 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 664 665 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 666 return Sym->getName() == *MP.MachOHeaderStartSymbol; 667 }); 668 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol"); 669 670 auto &JD = MR.getTargetJITDylib(); 671 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 672 auto HeaderAddr = (*I)->getAddress(); 673 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 674 assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); 675 MP.InitSeqs.insert( 676 std::make_pair(&JD, MachOJITDylibInitializers(JD.getName(), HeaderAddr))); 677 return Error::success(); 678 } 679 680 Error MachOPlatform::MachOPlatformPlugin::preserveInitSections( 681 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 682 683 JITLinkSymbolSet InitSectionSymbols; 684 for (auto &InitSectionName : InitSectionNames) { 685 // Skip non-init sections. 686 auto *InitSection = G.findSectionByName(InitSectionName); 687 if (!InitSection) 688 continue; 689 690 // Make a pass over live symbols in the section: those blocks are already 691 // preserved. 692 DenseSet<jitlink::Block *> AlreadyLiveBlocks; 693 for (auto &Sym : InitSection->symbols()) { 694 auto &B = Sym->getBlock(); 695 if (Sym->isLive() && Sym->getOffset() == 0 && 696 Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 697 InitSectionSymbols.insert(Sym); 698 AlreadyLiveBlocks.insert(&B); 699 } 700 } 701 702 // Add anonymous symbols to preserve any not-already-preserved blocks. 703 for (auto *B : InitSection->blocks()) 704 if (!AlreadyLiveBlocks.count(B)) 705 InitSectionSymbols.insert( 706 &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 707 } 708 709 if (!InitSectionSymbols.empty()) { 710 std::lock_guard<std::mutex> Lock(PluginMutex); 711 InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 712 } 713 714 return Error::success(); 715 } 716 717 Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo( 718 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 719 720 // If there's an ObjC imagine info then either 721 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In 722 // this case we name and record it. 723 // OR 724 // (2) We already have a recorded __objc_imageinfo for this JITDylib, 725 // in which case we just verify it. 726 auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName); 727 if (!ObjCImageInfo) 728 return Error::success(); 729 730 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); 731 732 // Check that the section is not empty if present. 733 if (llvm::empty(ObjCImageInfoBlocks)) 734 return make_error<StringError>("Empty " + ObjCImageInfoSectionName + 735 " section in " + G.getName(), 736 inconvertibleErrorCode()); 737 738 // Check that there's only one block in the section. 739 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) 740 return make_error<StringError>("Multiple blocks in " + 741 ObjCImageInfoSectionName + 742 " section in " + G.getName(), 743 inconvertibleErrorCode()); 744 745 // Check that the __objc_imageinfo section is unreferenced. 746 // FIXME: We could optimize this check if Symbols had a ref-count. 747 for (auto &Sec : G.sections()) { 748 if (&Sec != ObjCImageInfo) 749 for (auto *B : Sec.blocks()) 750 for (auto &E : B->edges()) 751 if (E.getTarget().isDefined() && 752 &E.getTarget().getBlock().getSection() == ObjCImageInfo) 753 return make_error<StringError>(ObjCImageInfoSectionName + 754 " is referenced within file " + 755 G.getName(), 756 inconvertibleErrorCode()); 757 } 758 759 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); 760 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); 761 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); 762 auto Flags = 763 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); 764 765 // Lock the mutex while we verify / update the ObjCImageInfos map. 766 std::lock_guard<std::mutex> Lock(PluginMutex); 767 768 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); 769 if (ObjCImageInfoItr != ObjCImageInfos.end()) { 770 // We've already registered an __objc_imageinfo section. Verify the 771 // content of this new section matches, then delete it. 772 if (ObjCImageInfoItr->second.first != Version) 773 return make_error<StringError>( 774 "ObjC version in " + G.getName() + 775 " does not match first registered version", 776 inconvertibleErrorCode()); 777 if (ObjCImageInfoItr->second.second != Flags) 778 return make_error<StringError>("ObjC flags in " + G.getName() + 779 " do not match first registered flags", 780 inconvertibleErrorCode()); 781 782 // __objc_imageinfo is valid. Delete the block. 783 for (auto *S : ObjCImageInfo->symbols()) 784 G.removeDefinedSymbol(*S); 785 G.removeBlock(ObjCImageInfoBlock); 786 } else { 787 // We haven't registered an __objc_imageinfo section yet. Register and 788 // move on. The section should already be marked no-dead-strip. 789 ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags); 790 } 791 792 return Error::success(); 793 } 794 795 Error MachOPlatform::MachOPlatformPlugin::registerInitSections( 796 jitlink::LinkGraph &G, JITDylib &JD) { 797 798 ExecutorAddr ObjCImageInfoAddr; 799 SmallVector<jitlink::Section *> InitSections; 800 801 if (auto *ObjCImageInfoSec = G.findSectionByName(ObjCImageInfoSectionName)) { 802 if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) 803 ObjCImageInfoAddr = Addr; 804 } 805 806 for (auto InitSectionName : InitSectionNames) 807 if (auto *Sec = G.findSectionByName(InitSectionName)) 808 InitSections.push_back(Sec); 809 810 // Dump the scraped inits. 811 LLVM_DEBUG({ 812 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 813 if (ObjCImageInfoAddr) 814 dbgs() << " " << ObjCImageInfoSectionName << ": " 815 << formatv("{0:x}", ObjCImageInfoAddr.getValue()) << "\n"; 816 for (auto *Sec : InitSections) { 817 jitlink::SectionRange R(*Sec); 818 dbgs() << " " << Sec->getName() << ": " 819 << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; 820 } 821 }); 822 823 return MP.registerInitInfo(JD, ObjCImageInfoAddr, InitSections); 824 } 825 826 Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges( 827 jitlink::LinkGraph &G, JITDylib &JD) { 828 829 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr. 830 for (auto *Sym : G.external_symbols()) 831 if (Sym->getName() == "__tlv_bootstrap") { 832 Sym->setName("___orc_rt_macho_tlv_get_addr"); 833 break; 834 } 835 836 // Store key in __thread_vars struct fields. 837 if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) { 838 Optional<uint64_t> Key; 839 { 840 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 841 auto I = MP.JITDylibToPThreadKey.find(&JD); 842 if (I != MP.JITDylibToPThreadKey.end()) 843 Key = I->second; 844 } 845 846 if (!Key) { 847 if (auto KeyOrErr = MP.createPThreadKey()) 848 Key = *KeyOrErr; 849 else 850 return KeyOrErr.takeError(); 851 } 852 853 uint64_t PlatformKeyBits = 854 support::endian::byte_swap(*Key, G.getEndianness()); 855 856 for (auto *B : ThreadDataSec->blocks()) { 857 if (B->getSize() != 3 * G.getPointerSize()) 858 return make_error<StringError>("__thread_vars block at " + 859 formatv("{0:x}", B->getAddress()) + 860 " has unexpected size", 861 inconvertibleErrorCode()); 862 863 auto NewBlockContent = G.allocateBuffer(B->getSize()); 864 llvm::copy(B->getContent(), NewBlockContent.data()); 865 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits, 866 G.getPointerSize()); 867 B->setContent(NewBlockContent); 868 } 869 } 870 871 // Transform any TLV edges into GOT edges. 872 for (auto *B : G.blocks()) 873 for (auto &E : B->edges()) 874 if (E.getKind() == 875 jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable) 876 E.setKind(jitlink::x86_64:: 877 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable); 878 879 return Error::success(); 880 } 881 882 Error MachOPlatform::MachOPlatformPlugin::registerEHAndTLVSections( 883 jitlink::LinkGraph &G) { 884 885 // Add a pass to register the final addresses of the eh-frame and TLV sections 886 // with the runtime. 887 if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { 888 jitlink::SectionRange R(*EHFrameSection); 889 if (!R.empty()) 890 G.allocActions().push_back( 891 {cantFail( 892 WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 893 MP.orc_rt_macho_register_ehframe_section, R.getRange())), 894 cantFail( 895 WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 896 MP.orc_rt_macho_deregister_ehframe_section, R.getRange()))}); 897 } 898 899 // Get a pointer to the thread data section if there is one. It will be used 900 // below. 901 jitlink::Section *ThreadDataSection = 902 G.findSectionByName(ThreadDataSectionName); 903 904 // Handle thread BSS section if there is one. 905 if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) { 906 // If there's already a thread data section in this graph then merge the 907 // thread BSS section content into it, otherwise just treat the thread 908 // BSS section as the thread data section. 909 if (ThreadDataSection) 910 G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 911 else 912 ThreadDataSection = ThreadBSSSection; 913 } 914 915 // Having merged thread BSS (if present) and thread data (if present), 916 // record the resulting section range. 917 if (ThreadDataSection) { 918 jitlink::SectionRange R(*ThreadDataSection); 919 if (!R.empty()) { 920 if (MP.State != MachOPlatform::Initialized) 921 return make_error<StringError>("__thread_data section encountered, but " 922 "MachOPlatform has not finished booting", 923 inconvertibleErrorCode()); 924 925 G.allocActions().push_back( 926 {cantFail( 927 WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 928 MP.orc_rt_macho_register_thread_data_section, R.getRange())), 929 cantFail( 930 WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 931 MP.orc_rt_macho_deregister_thread_data_section, 932 R.getRange()))}); 933 } 934 } 935 return Error::success(); 936 } 937 938 Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1( 939 jitlink::LinkGraph &G) { 940 941 // If there's no eh-frame there's nothing to do. 942 auto *EHFrameSection = G.findSectionByName(EHFrameSectionName); 943 if (!EHFrameSection) 944 return Error::success(); 945 946 // If the eh-frame section is empty there's nothing to do. 947 jitlink::SectionRange R(*EHFrameSection); 948 if (R.empty()) 949 return Error::success(); 950 951 // Since we're linking the object containing the registration code now the 952 // addresses won't be ready in the platform. We'll have to find them in this 953 // graph instead. 954 ExecutorAddr orc_rt_macho_register_ehframe_section; 955 ExecutorAddr orc_rt_macho_deregister_ehframe_section; 956 for (auto *Sym : G.defined_symbols()) { 957 if (!Sym->hasName()) 958 continue; 959 if (Sym->getName() == "___orc_rt_macho_register_ehframe_section") 960 orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress()); 961 else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section") 962 orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress()); 963 964 if (orc_rt_macho_register_ehframe_section && 965 orc_rt_macho_deregister_ehframe_section) 966 break; 967 } 968 969 // If we failed to find the required functions then bail out. 970 if (!orc_rt_macho_register_ehframe_section || 971 !orc_rt_macho_deregister_ehframe_section) 972 return make_error<StringError>("Could not find eh-frame registration " 973 "functions during platform bootstrap", 974 inconvertibleErrorCode()); 975 976 // Otherwise, add allocation actions to the graph to register eh-frames for 977 // this object. 978 G.allocActions().push_back( 979 {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 980 orc_rt_macho_register_ehframe_section, R.getRange())), 981 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>( 982 orc_rt_macho_deregister_ehframe_section, R.getRange()))}); 983 984 return Error::success(); 985 } 986 987 } // End namespace orc. 988 } // End namespace llvm. 989