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/MachO.h" 13 #include "llvm/ExecutionEngine/JITLink/aarch64.h" 14 #include "llvm/ExecutionEngine/JITLink/x86_64.h" 15 #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 16 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 17 #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h" 18 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 19 #include "llvm/Support/BinaryByteStream.h" 20 #include "llvm/Support/Debug.h" 21 #include <optional> 22 23 #define DEBUG_TYPE "orc" 24 25 using namespace llvm; 26 using namespace llvm::orc; 27 using namespace llvm::orc::shared; 28 29 namespace llvm { 30 namespace orc { 31 namespace shared { 32 33 using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>; 34 using SPSMachOJITDylibDepInfoMap = 35 SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>; 36 37 template <> 38 class SPSSerializationTraits<SPSMachOJITDylibDepInfo, 39 MachOPlatform::MachOJITDylibDepInfo> { 40 public: 41 static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) { 42 return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders); 43 } 44 45 static bool serialize(SPSOutputBuffer &OB, 46 const MachOPlatform::MachOJITDylibDepInfo &DDI) { 47 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed, 48 DDI.DepHeaders); 49 } 50 51 static bool deserialize(SPSInputBuffer &IB, 52 MachOPlatform::MachOJITDylibDepInfo &DDI) { 53 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed, 54 DDI.DepHeaders); 55 } 56 }; 57 58 } // namespace shared 59 } // namespace orc 60 } // namespace llvm 61 62 namespace { 63 64 std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP, 65 std::string Name) { 66 unsigned PointerSize; 67 support::endianness Endianness; 68 const auto &TT = MOP.getExecutionSession().getTargetTriple(); 69 70 switch (TT.getArch()) { 71 case Triple::aarch64: 72 case Triple::x86_64: 73 PointerSize = 8; 74 Endianness = support::endianness::little; 75 break; 76 default: 77 llvm_unreachable("Unrecognized architecture"); 78 } 79 80 return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize, 81 Endianness, 82 jitlink::getGenericEdgeKindName); 83 } 84 85 // Generates a MachO header. 86 class MachOHeaderMaterializationUnit : public MaterializationUnit { 87 public: 88 MachOHeaderMaterializationUnit(MachOPlatform &MOP, 89 const SymbolStringPtr &HeaderStartSymbol) 90 : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)), 91 MOP(MOP) {} 92 93 StringRef getName() const override { return "MachOHeaderMU"; } 94 95 void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 96 auto G = createPlatformGraph(MOP, "<MachOHeaderMU>"); 97 addMachOHeader(*G, MOP, R->getInitializerSymbol()); 98 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 99 } 100 101 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 102 103 static void addMachOHeader(jitlink::LinkGraph &G, MachOPlatform &MOP, 104 const SymbolStringPtr &InitializerSymbol) { 105 auto &HeaderSection = G.createSection("__header", MemProt::Read); 106 auto &HeaderBlock = createHeaderBlock(G, HeaderSection); 107 108 // Init symbol is header-start symbol. 109 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, 110 HeaderBlock.getSize(), jitlink::Linkage::Strong, 111 jitlink::Scope::Default, false, true); 112 for (auto &HS : AdditionalHeaderSymbols) 113 G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(), 114 jitlink::Linkage::Strong, jitlink::Scope::Default, 115 false, true); 116 } 117 118 private: 119 struct HeaderSymbol { 120 const char *Name; 121 uint64_t Offset; 122 }; 123 124 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = { 125 {"___mh_executable_header", 0}}; 126 127 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G, 128 jitlink::Section &HeaderSection) { 129 MachO::mach_header_64 Hdr; 130 Hdr.magic = MachO::MH_MAGIC_64; 131 switch (G.getTargetTriple().getArch()) { 132 case Triple::aarch64: 133 Hdr.cputype = MachO::CPU_TYPE_ARM64; 134 Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 135 break; 136 case Triple::x86_64: 137 Hdr.cputype = MachO::CPU_TYPE_X86_64; 138 Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 139 break; 140 default: 141 llvm_unreachable("Unrecognized architecture"); 142 } 143 Hdr.filetype = MachO::MH_DYLIB; // Custom file type? 144 Hdr.ncmds = 0; 145 Hdr.sizeofcmds = 0; 146 Hdr.flags = 0; 147 Hdr.reserved = 0; 148 149 if (G.getEndianness() != support::endian::system_endianness()) 150 MachO::swapStruct(Hdr); 151 152 auto HeaderContent = G.allocateContent( 153 ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr))); 154 155 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8, 156 0); 157 } 158 159 static MaterializationUnit::Interface 160 createHeaderInterface(MachOPlatform &MOP, 161 const SymbolStringPtr &HeaderStartSymbol) { 162 SymbolFlagsMap HeaderSymbolFlags; 163 164 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 165 for (auto &HS : AdditionalHeaderSymbols) 166 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = 167 JITSymbolFlags::Exported; 168 169 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags), 170 HeaderStartSymbol); 171 } 172 173 MachOPlatform &MOP; 174 }; 175 176 constexpr MachOHeaderMaterializationUnit::HeaderSymbol 177 MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[]; 178 179 // Creates a Bootstrap-Complete LinkGraph to run deferred actions. 180 class MachOPlatformCompleteBootstrapMaterializationUnit 181 : public MaterializationUnit { 182 public: 183 MachOPlatformCompleteBootstrapMaterializationUnit( 184 MachOPlatform &MOP, StringRef PlatformJDName, 185 SymbolStringPtr CompleteBootstrapSymbol, shared::AllocActions DeferredAAs, 186 ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown, 187 ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib, 188 ExecutorAddr MachOHeaderAddr) 189 : MaterializationUnit( 190 {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}), 191 MOP(MOP), PlatformJDName(PlatformJDName), 192 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)), 193 DeferredAAs(std::move(DeferredAAs)), 194 PlatformBootstrap(PlatformBootstrap), 195 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib), 196 DeregisterJITDylib(DeregisterJITDylib), 197 MachOHeaderAddr(MachOHeaderAddr) {} 198 199 StringRef getName() const override { 200 return "MachOPlatformCompleteBootstrap"; 201 } 202 203 void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 204 using namespace jitlink; 205 auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>"); 206 auto &PlaceholderSection = 207 G->createSection("__orc_rt_cplt_bs", MemProt::Read); 208 auto &PlaceholderBlock = 209 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0); 210 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1, 211 Linkage::Strong, Scope::Hidden, false, true); 212 213 // Reserve space for the stolen actions, plus two extras. 214 G->allocActions().reserve(DeferredAAs.size() + 2); 215 216 // 1. Bootstrap the platform support code. 217 G->allocActions().push_back( 218 {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)), 219 cantFail( 220 WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))}); 221 222 // 2. Register the platform JITDylib. 223 G->allocActions().push_back( 224 {cantFail(WrapperFunctionCall::Create< 225 SPSArgList<SPSString, SPSExecutorAddr>>( 226 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)), 227 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 228 DeregisterJITDylib, MachOHeaderAddr))}); 229 230 // 3. Add the deferred actions to the graph. 231 std::move(DeferredAAs.begin(), DeferredAAs.end(), 232 std::back_inserter(G->allocActions())); 233 234 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 235 } 236 237 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 238 239 private: 240 MachOPlatform &MOP; 241 StringRef PlatformJDName; 242 SymbolStringPtr CompleteBootstrapSymbol; 243 shared::AllocActions DeferredAAs; 244 ExecutorAddr PlatformBootstrap; 245 ExecutorAddr PlatformShutdown; 246 ExecutorAddr RegisterJITDylib; 247 ExecutorAddr DeregisterJITDylib; 248 ExecutorAddr MachOHeaderAddr; 249 }; 250 251 static StringRef ObjCRuntimeObjectSectionsData[] = { 252 MachOObjCCatListSectionName, MachOObjCClassListSectionName, 253 MachOObjCClassRefsSectionName, MachOObjCConstSectionName, 254 MachOObjCDataSectionName, MachOObjCSelRefsSectionName}; 255 256 static StringRef ObjCRuntimeObjectSectionsText[] = { 257 MachOObjCClassNameSectionName, MachOObjCMethNameSectionName, 258 MachOObjCMethTypeSectionName, MachOSwift5TypesSectionName, 259 MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName, 260 MachOSwift5EntrySectionName, MachOSwift5ProtoSectionName, 261 MachOSwift5ProtosSectionName}; 262 263 static StringRef ObjCRuntimeObjectSectionName = 264 "__llvm_jitlink_ObjCRuntimeRegistrationObject"; 265 266 static StringRef ObjCImageInfoSymbolName = 267 "__llvm_jitlink_macho_objc_imageinfo"; 268 269 } // end anonymous namespace 270 271 namespace llvm { 272 namespace orc { 273 274 Expected<std::unique_ptr<MachOPlatform>> 275 MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 276 JITDylib &PlatformJD, 277 std::unique_ptr<DefinitionGenerator> OrcRuntime, 278 std::optional<SymbolAliasMap> RuntimeAliases) { 279 280 // If the target is not supported then bail out immediately. 281 if (!supportedTarget(ES.getTargetTriple())) 282 return make_error<StringError>("Unsupported MachOPlatform triple: " + 283 ES.getTargetTriple().str(), 284 inconvertibleErrorCode()); 285 286 auto &EPC = ES.getExecutorProcessControl(); 287 288 // Create default aliases if the caller didn't supply any. 289 if (!RuntimeAliases) 290 RuntimeAliases = standardPlatformAliases(ES); 291 292 // Define the aliases. 293 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 294 return std::move(Err); 295 296 // Add JIT-dispatch function support symbols. 297 if (auto Err = PlatformJD.define( 298 absoluteSymbols({{ES.intern("___orc_rt_jit_dispatch"), 299 {EPC.getJITDispatchInfo().JITDispatchFunction, 300 JITSymbolFlags::Exported}}, 301 {ES.intern("___orc_rt_jit_dispatch_ctx"), 302 {EPC.getJITDispatchInfo().JITDispatchContext, 303 JITSymbolFlags::Exported}}}))) 304 return std::move(Err); 305 306 // Create the instance. 307 Error Err = Error::success(); 308 auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform( 309 ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err)); 310 if (Err) 311 return std::move(Err); 312 return std::move(P); 313 } 314 315 Expected<std::unique_ptr<MachOPlatform>> 316 MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 317 JITDylib &PlatformJD, const char *OrcRuntimePath, 318 std::optional<SymbolAliasMap> RuntimeAliases) { 319 320 // Create a generator for the ORC runtime archive. 321 auto OrcRuntimeArchiveGenerator = 322 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); 323 if (!OrcRuntimeArchiveGenerator) 324 return OrcRuntimeArchiveGenerator.takeError(); 325 326 return Create(ES, ObjLinkingLayer, PlatformJD, 327 std::move(*OrcRuntimeArchiveGenerator), 328 std::move(RuntimeAliases)); 329 } 330 331 Error MachOPlatform::setupJITDylib(JITDylib &JD) { 332 if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>( 333 *this, MachOHeaderStartSymbol))) 334 return Err; 335 336 return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError(); 337 } 338 339 Error MachOPlatform::teardownJITDylib(JITDylib &JD) { 340 std::lock_guard<std::mutex> Lock(PlatformMutex); 341 auto I = JITDylibToHeaderAddr.find(&JD); 342 if (I != JITDylibToHeaderAddr.end()) { 343 assert(HeaderAddrToJITDylib.count(I->second) && 344 "HeaderAddrToJITDylib missing entry"); 345 HeaderAddrToJITDylib.erase(I->second); 346 JITDylibToHeaderAddr.erase(I); 347 } 348 JITDylibToPThreadKey.erase(&JD); 349 return Error::success(); 350 } 351 352 Error MachOPlatform::notifyAdding(ResourceTracker &RT, 353 const MaterializationUnit &MU) { 354 auto &JD = RT.getJITDylib(); 355 const auto &InitSym = MU.getInitializerSymbol(); 356 if (!InitSym) 357 return Error::success(); 358 359 RegisteredInitSymbols[&JD].add(InitSym, 360 SymbolLookupFlags::WeaklyReferencedSymbol); 361 LLVM_DEBUG({ 362 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU " 363 << MU.getName() << "\n"; 364 }); 365 return Error::success(); 366 } 367 368 Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { 369 llvm_unreachable("Not supported yet"); 370 } 371 372 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 373 ArrayRef<std::pair<const char *, const char *>> AL) { 374 for (auto &KV : AL) { 375 auto AliasName = ES.intern(KV.first); 376 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 377 Aliases[std::move(AliasName)] = {ES.intern(KV.second), 378 JITSymbolFlags::Exported}; 379 } 380 } 381 382 SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { 383 SymbolAliasMap Aliases; 384 addAliases(ES, Aliases, requiredCXXAliases()); 385 addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 386 return Aliases; 387 } 388 389 ArrayRef<std::pair<const char *, const char *>> 390 MachOPlatform::requiredCXXAliases() { 391 static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 392 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; 393 394 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 395 } 396 397 ArrayRef<std::pair<const char *, const char *>> 398 MachOPlatform::standardRuntimeUtilityAliases() { 399 static const std::pair<const char *, const char *> 400 StandardRuntimeUtilityAliases[] = { 401 {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, 402 {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"}, 403 {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"}, 404 {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"}, 405 {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"}, 406 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; 407 408 return ArrayRef<std::pair<const char *, const char *>>( 409 StandardRuntimeUtilityAliases); 410 } 411 412 bool MachOPlatform::supportedTarget(const Triple &TT) { 413 switch (TT.getArch()) { 414 case Triple::aarch64: 415 case Triple::x86_64: 416 return true; 417 default: 418 return false; 419 } 420 } 421 422 MachOPlatform::MachOPlatform( 423 ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 424 JITDylib &PlatformJD, 425 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err) 426 : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) { 427 ErrorAsOutParameter _(&Err); 428 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this)); 429 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 430 431 BootstrapInfo BI; 432 Bootstrap = &BI; 433 434 // Bootstrap process -- here be phase-ordering dragons. 435 // 436 // The MachOPlatform class uses allocation actions to register metadata 437 // sections with the ORC runtime, however the runtime contains metadata 438 // registration functions that have their own metadata that they need to 439 // register (e.g. the frame-info registration functions have frame-info). 440 // We can't use an ordinary lookup to find these registration functions 441 // because their address is needed during the link of the containing graph 442 // itself (to build the allocation actions that will call the registration 443 // functions). Further complicating the situation (a) the graph containing 444 // the registration functions is allowed to depend on other graphs (e.g. the 445 // graph containing the ORC runtime RTTI support) so we need to handle with 446 // an unknown set of dependencies during bootstrap, and (b) these graphs may 447 // be linked concurrently if the user has installed a concurrent dispatcher. 448 // 449 // We satisfy these constraint by implementing a bootstrap phase during which 450 // allocation actions generated by MachOPlatform are appended to a list of 451 // deferred allocation actions, rather than to the graphs themselves. At the 452 // end of the bootstrap process the deferred actions are attached to a final 453 // "complete-bootstrap" graph that causes them to be run. 454 // 455 // The bootstrap steps are as follows: 456 // 457 // 1. Request the graph containing the mach header. This graph is guaranteed 458 // not to have any metadata so the fact that the registration functions 459 // are not available yet is not a problem. 460 // 461 // 2. Look up the registration functions and discard the results. This will 462 // trigger linking of the graph containing these functions, and 463 // consequently any graphs that it depends on. We do not use the lookup 464 // result to find the addresses of the functions requested (as described 465 // above the lookup will return too late for that), instead we capture the 466 // addresses in a post-allocation pass injected by the platform runtime 467 // during bootstrap only. 468 // 469 // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of 470 // graphs being linked (potentially concurrently), and we block until all 471 // of these graphs have completed linking. This is to avoid a race on the 472 // deferred-actions vector: the lookup for the runtime registration 473 // functions may return while some functions (those that are being 474 // incidentally linked in, but aren't reachable via the runtime functions) 475 // are still being linked, and we need to capture any allocation actions 476 // for this incidental code before we proceed. 477 // 478 // 4. Once all active links are complete we transfer the deferred actions to 479 // a newly added CompleteBootstrap graph and then request a symbol from 480 // the CompleteBootstrap graph to trigger materialization. This will cause 481 // all deferred actions to be run, and once this lookup returns we can 482 // proceed. 483 // 484 // 5. Finally, we associate runtime support methods in MachOPlatform with 485 // the corresponding jit-dispatch tag variables in the ORC runtime to make 486 // the support methods callable. The bootstrap is now complete. 487 488 // Step (1) Add header materialization unit and request. 489 if ((Err = PlatformJD.define(std::make_unique<MachOHeaderMaterializationUnit>( 490 *this, MachOHeaderStartSymbol)))) 491 return; 492 if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError())) 493 return; 494 495 // Step (2) Request runtime registration functions to trigger 496 // materialization.. 497 if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD), 498 SymbolLookupSet( 499 {PlatformBootstrap.Name, PlatformShutdown.Name, 500 RegisterJITDylib.Name, DeregisterJITDylib.Name, 501 RegisterObjectPlatformSections.Name, 502 DeregisterObjectPlatformSections.Name, 503 CreatePThreadKey.Name})) 504 .takeError())) 505 return; 506 507 // Step (3) Wait for any incidental linker work to complete. 508 { 509 std::unique_lock<std::mutex> Lock(BI.Mutex); 510 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; }); 511 Bootstrap = nullptr; 512 } 513 514 // Step (4) Add complete-bootstrap materialization unit and request. 515 auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap"); 516 if ((Err = PlatformJD.define( 517 std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>( 518 *this, PlatformJD.getName(), BootstrapCompleteSymbol, 519 std::move(BI.DeferredAAs), PlatformBootstrap.Addr, 520 PlatformShutdown.Addr, RegisterJITDylib.Addr, 521 DeregisterJITDylib.Addr, BI.MachOHeaderAddr)))) 522 return; 523 if ((Err = ES.lookup(makeJITDylibSearchOrder( 524 &PlatformJD, JITDylibLookupFlags::MatchAllSymbols), 525 std::move(BootstrapCompleteSymbol)) 526 .takeError())) 527 return; 528 529 // (5) Associate runtime support functions. 530 if ((Err = associateRuntimeSupportFunctions())) 531 return; 532 } 533 534 Error MachOPlatform::associateRuntimeSupportFunctions() { 535 ExecutionSession::JITDispatchHandlerAssociationMap WFs; 536 537 using PushInitializersSPSSig = 538 SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr); 539 WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] = 540 ES.wrapAsyncWithSPS<PushInitializersSPSSig>( 541 this, &MachOPlatform::rt_pushInitializers); 542 543 using LookupSymbolSPSSig = 544 SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString); 545 WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] = 546 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this, 547 &MachOPlatform::rt_lookupSymbol); 548 549 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 550 } 551 552 void MachOPlatform::pushInitializersLoop( 553 PushInitializersSendResultFn SendResult, JITDylibSP JD) { 554 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 555 DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap; 556 SmallVector<JITDylib *, 16> Worklist({JD.get()}); 557 558 ES.runSessionLocked([&]() { 559 while (!Worklist.empty()) { 560 // FIXME: Check for defunct dylibs. 561 562 auto DepJD = Worklist.back(); 563 Worklist.pop_back(); 564 565 // If we've already visited this JITDylib on this iteration then continue. 566 if (JDDepMap.count(DepJD)) 567 continue; 568 569 // Add dep info. 570 auto &DM = JDDepMap[DepJD]; 571 DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) { 572 for (auto &KV : O) { 573 if (KV.first == DepJD) 574 continue; 575 DM.push_back(KV.first); 576 Worklist.push_back(KV.first); 577 } 578 }); 579 580 // Add any registered init symbols. 581 auto RISItr = RegisteredInitSymbols.find(DepJD); 582 if (RISItr != RegisteredInitSymbols.end()) { 583 NewInitSymbols[DepJD] = std::move(RISItr->second); 584 RegisteredInitSymbols.erase(RISItr); 585 } 586 } 587 }); 588 589 // If there are no further init symbols to look up then send the link order 590 // (as a list of header addresses) to the caller. 591 if (NewInitSymbols.empty()) { 592 593 // To make the list intelligible to the runtime we need to convert all 594 // JITDylib pointers to their header addresses. Only include JITDylibs 595 // that appear in the JITDylibToHeaderAddr map (i.e. those that have been 596 // through setupJITDylib) -- bare JITDylibs aren't managed by the platform. 597 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs; 598 HeaderAddrs.reserve(JDDepMap.size()); 599 { 600 std::lock_guard<std::mutex> Lock(PlatformMutex); 601 for (auto &KV : JDDepMap) { 602 auto I = JITDylibToHeaderAddr.find(KV.first); 603 if (I != JITDylibToHeaderAddr.end()) 604 HeaderAddrs[KV.first] = I->second; 605 } 606 } 607 608 // Build the dep info map to return. 609 MachOJITDylibDepInfoMap DIM; 610 DIM.reserve(JDDepMap.size()); 611 for (auto &KV : JDDepMap) { 612 auto HI = HeaderAddrs.find(KV.first); 613 // Skip unmanaged JITDylibs. 614 if (HI == HeaderAddrs.end()) 615 continue; 616 auto H = HI->second; 617 MachOJITDylibDepInfo DepInfo; 618 for (auto &Dep : KV.second) { 619 auto HJ = HeaderAddrs.find(Dep); 620 if (HJ != HeaderAddrs.end()) 621 DepInfo.DepHeaders.push_back(HJ->second); 622 } 623 DIM.push_back(std::make_pair(H, std::move(DepInfo))); 624 } 625 SendResult(DIM); 626 return; 627 } 628 629 // Otherwise issue a lookup and re-run this phase when it completes. 630 lookupInitSymbolsAsync( 631 [this, SendResult = std::move(SendResult), JD](Error Err) mutable { 632 if (Err) 633 SendResult(std::move(Err)); 634 else 635 pushInitializersLoop(std::move(SendResult), JD); 636 }, 637 ES, std::move(NewInitSymbols)); 638 } 639 640 void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult, 641 ExecutorAddr JDHeaderAddr) { 642 JITDylibSP JD; 643 { 644 std::lock_guard<std::mutex> Lock(PlatformMutex); 645 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr); 646 if (I != HeaderAddrToJITDylib.end()) 647 JD = I->second; 648 } 649 650 LLVM_DEBUG({ 651 dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") "; 652 if (JD) 653 dbgs() << "pushing initializers for " << JD->getName() << "\n"; 654 else 655 dbgs() << "No JITDylib for header address.\n"; 656 }); 657 658 if (!JD) { 659 SendResult(make_error<StringError>("No JITDylib with header addr " + 660 formatv("{0:x}", JDHeaderAddr), 661 inconvertibleErrorCode())); 662 return; 663 } 664 665 pushInitializersLoop(std::move(SendResult), JD); 666 } 667 668 void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 669 ExecutorAddr Handle, StringRef SymbolName) { 670 LLVM_DEBUG({ 671 dbgs() << "MachOPlatform::rt_lookupSymbol(\"" << Handle << "\")\n"; 672 }); 673 674 JITDylib *JD = nullptr; 675 676 { 677 std::lock_guard<std::mutex> Lock(PlatformMutex); 678 auto I = HeaderAddrToJITDylib.find(Handle); 679 if (I != HeaderAddrToJITDylib.end()) 680 JD = I->second; 681 } 682 683 if (!JD) { 684 LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n"); 685 SendResult(make_error<StringError>("No JITDylib associated with handle " + 686 formatv("{0:x}", Handle), 687 inconvertibleErrorCode())); 688 return; 689 } 690 691 // Use functor class to work around XL build compiler issue on AIX. 692 class RtLookupNotifyComplete { 693 public: 694 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 695 : SendResult(std::move(SendResult)) {} 696 void operator()(Expected<SymbolMap> Result) { 697 if (Result) { 698 assert(Result->size() == 1 && "Unexpected result map count"); 699 SendResult(Result->begin()->second.getAddress()); 700 } else { 701 SendResult(Result.takeError()); 702 } 703 } 704 705 private: 706 SendSymbolAddressFn SendResult; 707 }; 708 709 // FIXME: Proper mangling. 710 auto MangledName = ("_" + SymbolName).str(); 711 ES.lookup( 712 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 713 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, 714 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 715 } 716 717 Expected<uint64_t> MachOPlatform::createPThreadKey() { 718 if (!CreatePThreadKey.Addr) 719 return make_error<StringError>( 720 "Attempting to create pthread key in target, but runtime support has " 721 "not been loaded yet", 722 inconvertibleErrorCode()); 723 724 Expected<uint64_t> Result(0); 725 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 726 CreatePThreadKey.Addr, Result)) 727 return std::move(Err); 728 return Result; 729 } 730 731 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 732 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 733 jitlink::PassConfiguration &Config) { 734 735 using namespace jitlink; 736 737 bool InBootstrapPhase = 738 &MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap; 739 740 // If we're in the bootstrap phase then increment the active graphs. 741 if (InBootstrapPhase) { 742 Config.PrePrunePasses.push_back( 743 [this](LinkGraph &G) { return bootstrapPipelineStart(G); }); 744 Config.PostAllocationPasses.push_back([this](LinkGraph &G) { 745 return bootstrapPipelineRecordRuntimeFunctions(G); 746 }); 747 } 748 749 // --- Handle Initializers --- 750 if (auto InitSymbol = MR.getInitializerSymbol()) { 751 752 // If the initializer symbol is the MachOHeader start symbol then just 753 // register it and then bail out -- the header materialization unit 754 // definitely doesn't need any other passes. 755 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) { 756 Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) { 757 return associateJITDylibHeaderSymbol(G, MR); 758 }); 759 return; 760 } 761 762 // If the object contains an init symbol other than the header start symbol 763 // then add passes to preserve, process and register the init 764 // sections/symbols. 765 Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) { 766 if (auto Err = preserveImportantSections(G, MR)) 767 return Err; 768 return processObjCImageInfo(G, MR); 769 }); 770 Config.PostPrunePasses.push_back( 771 [this](LinkGraph &G) { return createObjCRuntimeObject(G); }); 772 Config.PostAllocationPasses.push_back( 773 [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); }); 774 } 775 776 // Insert TLV lowering at the start of the PostPrunePasses, since we want 777 // it to run before GOT/PLT lowering. 778 Config.PostPrunePasses.insert( 779 Config.PostPrunePasses.begin(), 780 [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) { 781 return fixTLVSectionsAndEdges(G, JD); 782 }); 783 784 // Add a pass to register the final addresses of any special sections in the 785 // object with the runtime. 786 Config.PostAllocationPasses.push_back( 787 [this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) { 788 return registerObjectPlatformSections(G, JD, InBootstrapPhase); 789 }); 790 791 // If we're in the bootstrap phase then steal allocation actions and then 792 // decrement the active graphs. 793 if (InBootstrapPhase) 794 Config.PostFixupPasses.push_back( 795 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); }); 796 } 797 798 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 799 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 800 MaterializationResponsibility &MR) { 801 std::lock_guard<std::mutex> Lock(PluginMutex); 802 auto I = InitSymbolDeps.find(&MR); 803 if (I != InitSymbolDeps.end()) { 804 SyntheticSymbolDependenciesMap Result; 805 Result[MR.getInitializerSymbol()] = std::move(I->second); 806 InitSymbolDeps.erase(&MR); 807 return Result; 808 } 809 return SyntheticSymbolDependenciesMap(); 810 } 811 812 Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart( 813 jitlink::LinkGraph &G) { 814 // Increment the active graphs count in BootstrapInfo. 815 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex); 816 ++MP.Bootstrap.load()->ActiveGraphs; 817 return Error::success(); 818 } 819 820 Error MachOPlatform::MachOPlatformPlugin:: 821 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) { 822 // Record bootstrap function names. 823 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = { 824 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr}, 825 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr}, 826 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr}, 827 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr}, 828 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr}, 829 {*MP.RegisterObjectPlatformSections.Name, 830 &MP.RegisterObjectPlatformSections.Addr}, 831 {*MP.DeregisterObjectPlatformSections.Name, 832 &MP.DeregisterObjectPlatformSections.Addr}, 833 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}, 834 {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr}, 835 {*MP.DeregisterObjCRuntimeObject.Name, 836 &MP.DeregisterObjCRuntimeObject.Addr}}; 837 838 bool RegisterMachOHeader = false; 839 840 for (auto *Sym : G.defined_symbols()) { 841 for (auto &RTSym : RuntimeSymbols) { 842 if (Sym->hasName() && Sym->getName() == RTSym.first) { 843 if (*RTSym.second) 844 return make_error<StringError>( 845 "Duplicate " + RTSym.first + 846 " detected during MachOPlatform bootstrap", 847 inconvertibleErrorCode()); 848 849 if (Sym->getName() == *MP.MachOHeaderStartSymbol) 850 RegisterMachOHeader = true; 851 852 *RTSym.second = Sym->getAddress(); 853 } 854 } 855 } 856 857 if (RegisterMachOHeader) { 858 // If this graph defines the macho header symbol then create the internal 859 // mapping between it and PlatformJD. 860 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 861 MP.JITDylibToHeaderAddr[&MP.PlatformJD] = 862 MP.Bootstrap.load()->MachOHeaderAddr; 863 MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] = 864 &MP.PlatformJD; 865 } 866 867 return Error::success(); 868 } 869 870 Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd( 871 jitlink::LinkGraph &G) { 872 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex); 873 assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed"); 874 --MP.Bootstrap.load()->ActiveGraphs; 875 // Notify Bootstrap->CV while holding the mutex because the mutex is 876 // also keeping Bootstrap->CV alive. 877 if (MP.Bootstrap.load()->ActiveGraphs == 0) 878 MP.Bootstrap.load()->CV.notify_all(); 879 return Error::success(); 880 } 881 882 Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol( 883 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 884 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 885 return Sym->getName() == *MP.MachOHeaderStartSymbol; 886 }); 887 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol"); 888 889 auto &JD = MR.getTargetJITDylib(); 890 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 891 auto HeaderAddr = (*I)->getAddress(); 892 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr; 893 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 894 // We can unconditionally add these actions to the Graph because this pass 895 // isn't used during bootstrap. 896 G.allocActions().push_back( 897 {cantFail( 898 WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>( 899 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)), 900 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 901 MP.DeregisterJITDylib.Addr, HeaderAddr))}); 902 return Error::success(); 903 } 904 905 Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections( 906 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 907 // __objc_imageinfo is "important": we want to preserve it and record its 908 // address in the first graph that it appears in, then verify and discard it 909 // in all subsequent graphs. In this pass we preserve unconditionally -- we'll 910 // manually throw it away in the processObjCImageInfo pass. 911 if (auto *ObjCImageInfoSec = 912 G.findSectionByName(MachOObjCImageInfoSectionName)) { 913 if (ObjCImageInfoSec->blocks_size() != 1) 914 return make_error<StringError>( 915 "In " + G.getName() + 916 "__DATA,__objc_imageinfo contains multiple blocks", 917 inconvertibleErrorCode()); 918 G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false, 919 true); 920 921 for (auto *B : ObjCImageInfoSec->blocks()) 922 if (!B->edges_empty()) 923 return make_error<StringError>("In " + G.getName() + ", " + 924 MachOObjCImageInfoSectionName + 925 " contains references to symbols", 926 inconvertibleErrorCode()); 927 } 928 929 // Init sections are important: We need to preserve them and so that their 930 // addresses can be captured and reported to the ORC runtime in 931 // registerObjectPlatformSections. 932 JITLinkSymbolSet InitSectionSymbols; 933 for (auto &InitSectionName : MachOInitSectionNames) { 934 // Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may 935 // remove it later. 936 if (InitSectionName == MachOObjCImageInfoSectionName) 937 continue; 938 939 // Skip non-init sections. 940 auto *InitSection = G.findSectionByName(InitSectionName); 941 if (!InitSection) 942 continue; 943 944 // Make a pass over live symbols in the section: those blocks are already 945 // preserved. 946 DenseSet<jitlink::Block *> AlreadyLiveBlocks; 947 for (auto &Sym : InitSection->symbols()) { 948 auto &B = Sym->getBlock(); 949 if (Sym->isLive() && Sym->getOffset() == 0 && 950 Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 951 InitSectionSymbols.insert(Sym); 952 AlreadyLiveBlocks.insert(&B); 953 } 954 } 955 956 // Add anonymous symbols to preserve any not-already-preserved blocks. 957 for (auto *B : InitSection->blocks()) 958 if (!AlreadyLiveBlocks.count(B)) 959 InitSectionSymbols.insert( 960 &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 961 } 962 963 if (!InitSectionSymbols.empty()) { 964 std::lock_guard<std::mutex> Lock(PluginMutex); 965 InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 966 } 967 968 return Error::success(); 969 } 970 971 Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo( 972 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 973 974 // If there's an ObjC imagine info then either 975 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In 976 // this case we name and record it. 977 // OR 978 // (2) We already have a recorded __objc_imageinfo for this JITDylib, 979 // in which case we just verify it. 980 auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName); 981 if (!ObjCImageInfo) 982 return Error::success(); 983 984 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); 985 986 // Check that the section is not empty if present. 987 if (ObjCImageInfoBlocks.empty()) 988 return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName + 989 " section in " + G.getName(), 990 inconvertibleErrorCode()); 991 992 // Check that there's only one block in the section. 993 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) 994 return make_error<StringError>("Multiple blocks in " + 995 MachOObjCImageInfoSectionName + 996 " section in " + G.getName(), 997 inconvertibleErrorCode()); 998 999 // Check that the __objc_imageinfo section is unreferenced. 1000 // FIXME: We could optimize this check if Symbols had a ref-count. 1001 for (auto &Sec : G.sections()) { 1002 if (&Sec != ObjCImageInfo) 1003 for (auto *B : Sec.blocks()) 1004 for (auto &E : B->edges()) 1005 if (E.getTarget().isDefined() && 1006 &E.getTarget().getBlock().getSection() == ObjCImageInfo) 1007 return make_error<StringError>(MachOObjCImageInfoSectionName + 1008 " is referenced within file " + 1009 G.getName(), 1010 inconvertibleErrorCode()); 1011 } 1012 1013 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); 1014 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); 1015 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); 1016 auto Flags = 1017 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); 1018 1019 // Lock the mutex while we verify / update the ObjCImageInfos map. 1020 std::lock_guard<std::mutex> Lock(PluginMutex); 1021 1022 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); 1023 if (ObjCImageInfoItr != ObjCImageInfos.end()) { 1024 // We've already registered an __objc_imageinfo section. Verify the 1025 // content of this new section matches, then delete it. 1026 if (ObjCImageInfoItr->second.Version != Version) 1027 return make_error<StringError>( 1028 "ObjC version in " + G.getName() + 1029 " does not match first registered version", 1030 inconvertibleErrorCode()); 1031 if (ObjCImageInfoItr->second.Flags != Flags) 1032 return make_error<StringError>("ObjC flags in " + G.getName() + 1033 " do not match first registered flags", 1034 inconvertibleErrorCode()); 1035 1036 // __objc_imageinfo is valid. Delete the block. 1037 for (auto *S : ObjCImageInfo->symbols()) 1038 G.removeDefinedSymbol(*S); 1039 G.removeBlock(ObjCImageInfoBlock); 1040 } else { 1041 // We haven't registered an __objc_imageinfo section yet. Register and 1042 // move on. The section should already be marked no-dead-strip. 1043 G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName, 1044 ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong, 1045 jitlink::Scope::Hidden, false, true); 1046 if (auto Err = MR.defineMaterializing( 1047 {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName), 1048 JITSymbolFlags()}})) 1049 return Err; 1050 ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags}; 1051 } 1052 1053 return Error::success(); 1054 } 1055 1056 Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges( 1057 jitlink::LinkGraph &G, JITDylib &JD) { 1058 1059 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr. 1060 for (auto *Sym : G.external_symbols()) 1061 if (Sym->getName() == "__tlv_bootstrap") { 1062 Sym->setName("___orc_rt_macho_tlv_get_addr"); 1063 break; 1064 } 1065 1066 // Store key in __thread_vars struct fields. 1067 if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) { 1068 std::optional<uint64_t> Key; 1069 { 1070 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 1071 auto I = MP.JITDylibToPThreadKey.find(&JD); 1072 if (I != MP.JITDylibToPThreadKey.end()) 1073 Key = I->second; 1074 } 1075 1076 if (!Key) { 1077 if (auto KeyOrErr = MP.createPThreadKey()) 1078 Key = *KeyOrErr; 1079 else 1080 return KeyOrErr.takeError(); 1081 } 1082 1083 uint64_t PlatformKeyBits = 1084 support::endian::byte_swap(*Key, G.getEndianness()); 1085 1086 for (auto *B : ThreadDataSec->blocks()) { 1087 if (B->getSize() != 3 * G.getPointerSize()) 1088 return make_error<StringError>("__thread_vars block at " + 1089 formatv("{0:x}", B->getAddress()) + 1090 " has unexpected size", 1091 inconvertibleErrorCode()); 1092 1093 auto NewBlockContent = G.allocateBuffer(B->getSize()); 1094 llvm::copy(B->getContent(), NewBlockContent.data()); 1095 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits, 1096 G.getPointerSize()); 1097 B->setContent(NewBlockContent); 1098 } 1099 } 1100 1101 // Transform any TLV edges into GOT edges. 1102 for (auto *B : G.blocks()) 1103 for (auto &E : B->edges()) 1104 if (E.getKind() == 1105 jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable) 1106 E.setKind(jitlink::x86_64:: 1107 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable); 1108 1109 return Error::success(); 1110 } 1111 1112 std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections> 1113 MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo( 1114 jitlink::LinkGraph &G) { 1115 using namespace jitlink; 1116 1117 UnwindSections US; 1118 1119 // ScanSection records a section range and adds any executable blocks that 1120 // that section points to to the CodeBlocks vector. 1121 SmallVector<Block *> CodeBlocks; 1122 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) { 1123 if (Sec.blocks().empty()) 1124 return; 1125 SecRange = (*Sec.blocks().begin())->getRange(); 1126 for (auto *B : Sec.blocks()) { 1127 auto R = B->getRange(); 1128 SecRange.Start = std::min(SecRange.Start, R.Start); 1129 SecRange.End = std::max(SecRange.End, R.End); 1130 for (auto &E : B->edges()) { 1131 if (!E.getTarget().isDefined()) 1132 continue; 1133 auto &TargetBlock = E.getTarget().getBlock(); 1134 auto &TargetSection = TargetBlock.getSection(); 1135 if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec) 1136 CodeBlocks.push_back(&TargetBlock); 1137 } 1138 } 1139 }; 1140 1141 if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) 1142 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection); 1143 1144 if (Section *CUInfoSec = 1145 G.findSectionByName(MachOCompactUnwindInfoSectionName)) 1146 ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection); 1147 1148 // If we didn't find any pointed-to code-blocks then there's no need to 1149 // register any info. 1150 if (CodeBlocks.empty()) 1151 return std::nullopt; 1152 1153 // We have info to register. Sort the code blocks into address order and 1154 // build a list of contiguous address ranges covering them all. 1155 llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) { 1156 return LHS->getAddress() < RHS->getAddress(); 1157 }); 1158 for (auto *B : CodeBlocks) { 1159 if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress()) 1160 US.CodeRanges.push_back(B->getRange()); 1161 else 1162 US.CodeRanges.back().End = B->getRange().End; 1163 } 1164 1165 LLVM_DEBUG({ 1166 dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n" 1167 << " DWARF: "; 1168 if (US.DwarfSection.Start) 1169 dbgs() << US.DwarfSection << "\n"; 1170 else 1171 dbgs() << "none\n"; 1172 dbgs() << " Compact-unwind: "; 1173 if (US.CompactUnwindSection.Start) 1174 dbgs() << US.CompactUnwindSection << "\n"; 1175 else 1176 dbgs() << "none\n" 1177 << "for code ranges:\n"; 1178 for (auto &CR : US.CodeRanges) 1179 dbgs() << " " << CR << "\n"; 1180 if (US.CodeRanges.size() >= G.sections_size()) 1181 dbgs() << "WARNING: High number of discontiguous code ranges! " 1182 "Padding may be interfering with coalescing.\n"; 1183 }); 1184 1185 return US; 1186 } 1187 1188 Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections( 1189 jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) { 1190 1191 // Get a pointer to the thread data section if there is one. It will be used 1192 // below. 1193 jitlink::Section *ThreadDataSection = 1194 G.findSectionByName(MachOThreadDataSectionName); 1195 1196 // Handle thread BSS section if there is one. 1197 if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) { 1198 // If there's already a thread data section in this graph then merge the 1199 // thread BSS section content into it, otherwise just treat the thread 1200 // BSS section as the thread data section. 1201 if (ThreadDataSection) 1202 G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 1203 else 1204 ThreadDataSection = ThreadBSSSection; 1205 } 1206 1207 SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs; 1208 1209 // Collect data sections to register. 1210 StringRef DataSections[] = {MachODataDataSectionName, 1211 MachODataCommonSectionName, 1212 MachOEHFrameSectionName}; 1213 for (auto &SecName : DataSections) { 1214 if (auto *Sec = G.findSectionByName(SecName)) { 1215 jitlink::SectionRange R(*Sec); 1216 if (!R.empty()) 1217 MachOPlatformSecs.push_back({SecName, R.getRange()}); 1218 } 1219 } 1220 1221 // Having merged thread BSS (if present) and thread data (if present), 1222 // record the resulting section range. 1223 if (ThreadDataSection) { 1224 jitlink::SectionRange R(*ThreadDataSection); 1225 if (!R.empty()) 1226 MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()}); 1227 } 1228 1229 // If any platform sections were found then add an allocation action to call 1230 // the registration function. 1231 StringRef PlatformSections[] = {MachOModInitFuncSectionName, 1232 ObjCRuntimeObjectSectionName}; 1233 1234 for (auto &SecName : PlatformSections) { 1235 auto *Sec = G.findSectionByName(SecName); 1236 if (!Sec) 1237 continue; 1238 jitlink::SectionRange R(*Sec); 1239 if (R.empty()) 1240 continue; 1241 1242 MachOPlatformSecs.push_back({SecName, R.getRange()}); 1243 } 1244 1245 std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange, 1246 ExecutorAddrRange>> 1247 UnwindInfo; 1248 if (auto UI = findUnwindSectionInfo(G)) 1249 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection, 1250 UI->CompactUnwindSection); 1251 1252 if (!MachOPlatformSecs.empty() || UnwindInfo) { 1253 ExecutorAddr HeaderAddr; 1254 { 1255 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 1256 auto I = MP.JITDylibToHeaderAddr.find(&JD); 1257 assert(I != MP.JITDylibToHeaderAddr.end() && 1258 "Missing header for JITDylib"); 1259 HeaderAddr = I->second; 1260 } 1261 1262 // Dump the scraped inits. 1263 LLVM_DEBUG({ 1264 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 1265 for (auto &KV : MachOPlatformSecs) 1266 dbgs() << " " << KV.first << ": " << KV.second << "\n"; 1267 }); 1268 1269 using SPSRegisterObjectPlatformSectionsArgs = SPSArgList< 1270 SPSExecutorAddr, 1271 SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>, 1272 SPSExecutorAddrRange, SPSExecutorAddrRange>>, 1273 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>; 1274 1275 shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase) 1276 ? G.allocActions() 1277 : MP.Bootstrap.load()->DeferredAAs; 1278 1279 allocActions.push_back( 1280 {cantFail( 1281 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1282 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo, 1283 MachOPlatformSecs)), 1284 cantFail( 1285 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1286 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr, 1287 UnwindInfo, MachOPlatformSecs))}); 1288 } 1289 1290 return Error::success(); 1291 } 1292 1293 Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject( 1294 jitlink::LinkGraph &G) { 1295 1296 bool NeedTextSegment = false; 1297 size_t NumRuntimeSections = 0; 1298 1299 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) 1300 if (G.findSectionByName(ObjCRuntimeSectionName)) 1301 ++NumRuntimeSections; 1302 1303 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 1304 if (G.findSectionByName(ObjCRuntimeSectionName)) { 1305 ++NumRuntimeSections; 1306 NeedTextSegment = true; 1307 } 1308 } 1309 1310 // Early out for no runtime sections. 1311 if (NumRuntimeSections == 0) 1312 return Error::success(); 1313 1314 // If there were any runtime sections then we need to add an __objc_imageinfo 1315 // section. 1316 ++NumRuntimeSections; 1317 1318 size_t MachOSize = sizeof(MachO::mach_header_64) + 1319 (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) + 1320 NumRuntimeSections * sizeof(MachO::section_64); 1321 1322 auto &Sec = G.createSection(ObjCRuntimeObjectSectionName, 1323 MemProt::Read | MemProt::Write); 1324 G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true); 1325 1326 return Error::success(); 1327 } 1328 1329 Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject( 1330 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 1331 1332 auto *ObjCRuntimeObjectSec = 1333 G.findSectionByName(ObjCRuntimeObjectSectionName); 1334 1335 if (!ObjCRuntimeObjectSec) 1336 return Error::success(); 1337 1338 switch (G.getTargetTriple().getArch()) { 1339 case Triple::aarch64: 1340 case Triple::x86_64: 1341 // Supported. 1342 break; 1343 default: 1344 return make_error<StringError>("Unrecognized MachO arch in triple " + 1345 G.getTargetTriple().str(), 1346 inconvertibleErrorCode()); 1347 } 1348 1349 auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin(); 1350 1351 struct SecDesc { 1352 MachO::section_64 Sec; 1353 unique_function<void(size_t RecordOffset)> AddFixups; 1354 }; 1355 1356 std::vector<SecDesc> TextSections, DataSections; 1357 auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) { 1358 jitlink::SectionRange SR(GraphSec); 1359 StringRef FQName = GraphSec.getName(); 1360 memset(&SD.Sec, 0, sizeof(MachO::section_64)); 1361 memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7); 1362 memcpy(SD.Sec.segname, FQName.data(), 6); 1363 SD.Sec.addr = SR.getStart() - SecBlock.getAddress(); 1364 SD.Sec.size = SR.getSize(); 1365 SD.Sec.flags = MachO::S_REGULAR; 1366 }; 1367 1368 // Add the __objc_imageinfo section. 1369 { 1370 DataSections.push_back({}); 1371 auto &SD = DataSections.back(); 1372 memset(&SD.Sec, 0, sizeof(SD.Sec)); 1373 memcpy(SD.Sec.sectname, "__objc_imageinfo", 16); 1374 strcpy(SD.Sec.segname, "__DATA"); 1375 SD.Sec.size = 8; 1376 SD.AddFixups = [&](size_t RecordOffset) { 1377 jitlink::Edge::Kind PointerEdge = jitlink::Edge::Invalid; 1378 switch (G.getTargetTriple().getArch()) { 1379 case Triple::aarch64: 1380 PointerEdge = jitlink::aarch64::Pointer64; 1381 break; 1382 case Triple::x86_64: 1383 PointerEdge = jitlink::x86_64::Pointer64; 1384 break; 1385 default: 1386 llvm_unreachable("Unsupported architecture"); 1387 } 1388 1389 // Look for an existing __objc_imageinfo symbol. 1390 jitlink::Symbol *ObjCImageInfoSym = nullptr; 1391 for (auto *Sym : G.external_symbols()) 1392 if (Sym->getName() == ObjCImageInfoSymbolName) { 1393 ObjCImageInfoSym = Sym; 1394 break; 1395 } 1396 if (!ObjCImageInfoSym) 1397 for (auto *Sym : G.absolute_symbols()) 1398 if (Sym->getName() == ObjCImageInfoSymbolName) { 1399 ObjCImageInfoSym = Sym; 1400 break; 1401 } 1402 if (!ObjCImageInfoSym) 1403 for (auto *Sym : G.defined_symbols()) 1404 if (Sym->hasName() && Sym->getName() == ObjCImageInfoSymbolName) { 1405 ObjCImageInfoSym = Sym; 1406 break; 1407 } 1408 if (!ObjCImageInfoSym) 1409 ObjCImageInfoSym = 1410 &G.addExternalSymbol(ObjCImageInfoSymbolName, 8, false); 1411 1412 SecBlock.addEdge(PointerEdge, 1413 RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec), 1414 *ObjCImageInfoSym, -SecBlock.getAddress().getValue()); 1415 }; 1416 } 1417 1418 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) { 1419 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 1420 DataSections.push_back({}); 1421 AddSection(DataSections.back(), *GraphSec); 1422 } 1423 } 1424 1425 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 1426 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 1427 TextSections.push_back({}); 1428 AddSection(TextSections.back(), *GraphSec); 1429 } 1430 } 1431 1432 assert(ObjCRuntimeObjectSec->blocks_size() == 1 && 1433 "Unexpected number of blocks in runtime sections object"); 1434 1435 // Build the header struct up-front. This also gives us a chance to check 1436 // that the triple is supported, which we'll assume below. 1437 MachO::mach_header_64 Hdr; 1438 Hdr.magic = MachO::MH_MAGIC_64; 1439 switch (G.getTargetTriple().getArch()) { 1440 case Triple::aarch64: 1441 Hdr.cputype = MachO::CPU_TYPE_ARM64; 1442 Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 1443 break; 1444 case Triple::x86_64: 1445 Hdr.cputype = MachO::CPU_TYPE_X86_64; 1446 Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 1447 break; 1448 default: 1449 llvm_unreachable("Unsupported architecture"); 1450 } 1451 1452 Hdr.filetype = MachO::MH_DYLIB; 1453 Hdr.ncmds = 1 + !TextSections.empty(); 1454 Hdr.sizeofcmds = 1455 Hdr.ncmds * sizeof(MachO::segment_command_64) + 1456 (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64); 1457 Hdr.flags = 0; 1458 Hdr.reserved = 0; 1459 1460 auto SecContent = SecBlock.getAlreadyMutableContent(); 1461 char *P = SecContent.data(); 1462 auto WriteMachOStruct = [&](auto S) { 1463 if (G.getEndianness() != support::endian::system_endianness()) 1464 MachO::swapStruct(S); 1465 memcpy(P, &S, sizeof(S)); 1466 P += sizeof(S); 1467 }; 1468 1469 auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) { 1470 MachO::segment_command_64 SegLC; 1471 memset(&SegLC, 0, sizeof(SegLC)); 1472 memcpy(SegLC.segname, Name.data(), Name.size()); 1473 SegLC.cmd = MachO::LC_SEGMENT_64; 1474 SegLC.cmdsize = sizeof(MachO::segment_command_64) + 1475 Secs.size() * sizeof(MachO::section_64); 1476 SegLC.nsects = Secs.size(); 1477 WriteMachOStruct(SegLC); 1478 for (auto &SD : Secs) { 1479 if (SD.AddFixups) 1480 SD.AddFixups(P - SecContent.data()); 1481 WriteMachOStruct(SD.Sec); 1482 } 1483 }; 1484 1485 WriteMachOStruct(Hdr); 1486 if (!TextSections.empty()) 1487 WriteSegment("__TEXT", TextSections); 1488 if (!DataSections.empty()) 1489 WriteSegment("__DATA", DataSections); 1490 1491 assert(P == SecContent.end() && "Underflow writing ObjC runtime object"); 1492 return Error::success(); 1493 } 1494 1495 } // End namespace orc. 1496 } // End namespace llvm. 1497