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