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