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