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/AbsoluteSymbols.h" 16 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 17 #include "llvm/ExecutionEngine/Orc/MachOBuilder.h" 18 #include "llvm/Support/Debug.h" 19 #include <optional> 20 21 #define DEBUG_TYPE "orc" 22 23 using namespace llvm; 24 using namespace llvm::orc; 25 using namespace llvm::orc::shared; 26 27 namespace llvm { 28 namespace orc { 29 namespace shared { 30 31 using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>; 32 using SPSMachOJITDylibDepInfoMap = 33 SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>; 34 35 class SPSMachOExecutorSymbolFlags; 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 template <> 59 class SPSSerializationTraits<SPSMachOExecutorSymbolFlags, 60 MachOPlatform::MachOExecutorSymbolFlags> { 61 private: 62 using UT = std::underlying_type_t<MachOPlatform::MachOExecutorSymbolFlags>; 63 64 public: 65 static size_t size(const MachOPlatform::MachOExecutorSymbolFlags &SF) { 66 return sizeof(UT); 67 } 68 69 static bool serialize(SPSOutputBuffer &OB, 70 const MachOPlatform::MachOExecutorSymbolFlags &SF) { 71 return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF)); 72 } 73 74 static bool deserialize(SPSInputBuffer &IB, 75 MachOPlatform::MachOExecutorSymbolFlags &SF) { 76 UT Tmp; 77 if (!SPSArgList<UT>::deserialize(IB, Tmp)) 78 return false; 79 SF = static_cast<MachOPlatform::MachOExecutorSymbolFlags>(Tmp); 80 return true; 81 } 82 }; 83 84 } // namespace shared 85 } // namespace orc 86 } // namespace llvm 87 88 namespace { 89 90 using SPSRegisterSymbolsArgs = 91 SPSArgList<SPSExecutorAddr, 92 SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 93 SPSMachOExecutorSymbolFlags>>>; 94 95 std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP, 96 std::string Name) { 97 auto &ES = MOP.getExecutionSession(); 98 return std::make_unique<jitlink::LinkGraph>( 99 std::move(Name), ES.getSymbolStringPool(), ES.getTargetTriple(), 100 SubtargetFeatures(), jitlink::getGenericEdgeKindName); 101 } 102 103 // Creates a Bootstrap-Complete LinkGraph to run deferred actions. 104 class MachOPlatformCompleteBootstrapMaterializationUnit 105 : public MaterializationUnit { 106 public: 107 using SymbolTableVector = 108 SmallVector<std::tuple<ExecutorAddr, ExecutorAddr, 109 MachOPlatform::MachOExecutorSymbolFlags>>; 110 111 MachOPlatformCompleteBootstrapMaterializationUnit( 112 MachOPlatform &MOP, StringRef PlatformJDName, 113 SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab, 114 shared::AllocActions DeferredAAs, ExecutorAddr MachOHeaderAddr, 115 ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown, 116 ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib, 117 ExecutorAddr RegisterObjectSymbolTable, 118 ExecutorAddr DeregisterObjectSymbolTable) 119 : MaterializationUnit( 120 {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}), 121 MOP(MOP), PlatformJDName(PlatformJDName), 122 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)), 123 SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)), 124 MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap), 125 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib), 126 DeregisterJITDylib(DeregisterJITDylib), 127 RegisterObjectSymbolTable(RegisterObjectSymbolTable), 128 DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {} 129 130 StringRef getName() const override { 131 return "MachOPlatformCompleteBootstrap"; 132 } 133 134 void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 135 using namespace jitlink; 136 auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>"); 137 auto &PlaceholderSection = 138 G->createSection("__orc_rt_cplt_bs", MemProt::Read); 139 auto &PlaceholderBlock = 140 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0); 141 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1, 142 Linkage::Strong, Scope::Hidden, false, true); 143 144 // Reserve space for the stolen actions, plus two extras. 145 G->allocActions().reserve(DeferredAAs.size() + 3); 146 147 // 1. Bootstrap the platform support code. 148 G->allocActions().push_back( 149 {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)), 150 cantFail( 151 WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))}); 152 153 // 2. Register the platform JITDylib. 154 G->allocActions().push_back( 155 {cantFail(WrapperFunctionCall::Create< 156 SPSArgList<SPSString, SPSExecutorAddr>>( 157 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)), 158 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 159 DeregisterJITDylib, MachOHeaderAddr))}); 160 161 // 3. Register deferred symbols. 162 G->allocActions().push_back( 163 {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 164 RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)), 165 cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 166 DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))}); 167 168 // 4. Add the deferred actions to the graph. 169 std::move(DeferredAAs.begin(), DeferredAAs.end(), 170 std::back_inserter(G->allocActions())); 171 172 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 173 } 174 175 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 176 177 private: 178 MachOPlatform &MOP; 179 StringRef PlatformJDName; 180 SymbolStringPtr CompleteBootstrapSymbol; 181 SymbolTableVector SymTab; 182 shared::AllocActions DeferredAAs; 183 ExecutorAddr MachOHeaderAddr; 184 ExecutorAddr PlatformBootstrap; 185 ExecutorAddr PlatformShutdown; 186 ExecutorAddr RegisterJITDylib; 187 ExecutorAddr DeregisterJITDylib; 188 ExecutorAddr RegisterObjectSymbolTable; 189 ExecutorAddr DeregisterObjectSymbolTable; 190 }; 191 192 static StringRef ObjCRuntimeObjectSectionsData[] = { 193 MachOObjCCatListSectionName, MachOObjCCatList2SectionName, 194 MachOObjCClassListSectionName, MachOObjCClassRefsSectionName, 195 MachOObjCConstSectionName, MachOObjCDataSectionName, 196 MachOObjCProtoListSectionName, MachOObjCProtoRefsSectionName, 197 MachOObjCNLCatListSectionName, MachOObjCNLClassListSectionName, 198 MachOObjCSelRefsSectionName}; 199 200 static StringRef ObjCRuntimeObjectSectionsText[] = { 201 MachOObjCClassNameSectionName, MachOObjCMethNameSectionName, 202 MachOObjCMethTypeSectionName, MachOSwift5TypesSectionName, 203 MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName, 204 MachOSwift5EntrySectionName, MachOSwift5ProtoSectionName, 205 MachOSwift5ProtosSectionName}; 206 207 static StringRef ObjCRuntimeObjectSectionName = 208 "__llvm_jitlink_ObjCRuntimeRegistrationObject"; 209 210 static StringRef ObjCImageInfoSymbolName = 211 "__llvm_jitlink_macho_objc_imageinfo"; 212 213 struct ObjCImageInfoFlags { 214 uint16_t SwiftABIVersion; 215 uint16_t SwiftVersion; 216 bool HasCategoryClassProperties; 217 bool HasSignedObjCClassROs; 218 219 static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4); 220 static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6); 221 222 explicit ObjCImageInfoFlags(uint32_t RawFlags) { 223 HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO; 224 HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES; 225 SwiftABIVersion = (RawFlags >> 8) & 0xFF; 226 SwiftVersion = (RawFlags >> 16) & 0xFFFF; 227 } 228 229 uint32_t rawFlags() const { 230 uint32_t Result = 0; 231 if (HasCategoryClassProperties) 232 Result |= HAS_CATEGORY_CLASS_PROPERTIES; 233 if (HasSignedObjCClassROs) 234 Result |= SIGNED_CLASS_RO; 235 Result |= (SwiftABIVersion << 8); 236 Result |= (SwiftVersion << 16); 237 return Result; 238 } 239 }; 240 } // end anonymous namespace 241 242 namespace llvm { 243 namespace orc { 244 245 std::optional<MachOPlatform::HeaderOptions::BuildVersionOpts> 246 MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT, 247 uint32_t MinOS, 248 uint32_t SDK) { 249 250 uint32_t Platform; 251 switch (TT.getOS()) { 252 case Triple::IOS: 253 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR 254 : MachO::PLATFORM_IOS; 255 break; 256 case Triple::MacOSX: 257 Platform = MachO::PLATFORM_MACOS; 258 break; 259 case Triple::TvOS: 260 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR 261 : MachO::PLATFORM_TVOS; 262 break; 263 case Triple::WatchOS: 264 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR 265 : MachO::PLATFORM_WATCHOS; 266 break; 267 case Triple::XROS: 268 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR 269 : MachO::PLATFORM_XROS; 270 break; 271 default: 272 return std::nullopt; 273 } 274 275 return MachOPlatform::HeaderOptions::BuildVersionOpts{Platform, MinOS, SDK}; 276 } 277 278 Expected<std::unique_ptr<MachOPlatform>> 279 MachOPlatform::Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, 280 std::unique_ptr<DefinitionGenerator> OrcRuntime, 281 HeaderOptions PlatformJDOpts, 282 MachOHeaderMUBuilder BuildMachOHeaderMU, 283 std::optional<SymbolAliasMap> RuntimeAliases) { 284 285 auto &ES = ObjLinkingLayer.getExecutionSession(); 286 287 // If the target is not supported then bail out immediately. 288 if (!supportedTarget(ES.getTargetTriple())) 289 return make_error<StringError>("Unsupported MachOPlatform triple: " + 290 ES.getTargetTriple().str(), 291 inconvertibleErrorCode()); 292 293 auto &EPC = ES.getExecutorProcessControl(); 294 295 // Create default aliases if the caller didn't supply any. 296 if (!RuntimeAliases) 297 RuntimeAliases = standardPlatformAliases(ES); 298 299 // Define the aliases. 300 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 301 return std::move(Err); 302 303 // Add JIT-dispatch function support symbols. 304 if (auto Err = PlatformJD.define( 305 absoluteSymbols({{ES.intern("___orc_rt_jit_dispatch"), 306 {EPC.getJITDispatchInfo().JITDispatchFunction, 307 JITSymbolFlags::Exported}}, 308 {ES.intern("___orc_rt_jit_dispatch_ctx"), 309 {EPC.getJITDispatchInfo().JITDispatchContext, 310 JITSymbolFlags::Exported}}}))) 311 return std::move(Err); 312 313 // Create the instance. 314 Error Err = Error::success(); 315 auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform( 316 ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), 317 std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), Err)); 318 if (Err) 319 return std::move(Err); 320 return std::move(P); 321 } 322 323 Expected<std::unique_ptr<MachOPlatform>> 324 MachOPlatform::Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, 325 const char *OrcRuntimePath, HeaderOptions PlatformJDOpts, 326 MachOHeaderMUBuilder BuildMachOHeaderMU, 327 std::optional<SymbolAliasMap> RuntimeAliases) { 328 329 // Create a generator for the ORC runtime archive. 330 auto OrcRuntimeArchiveGenerator = 331 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); 332 if (!OrcRuntimeArchiveGenerator) 333 return OrcRuntimeArchiveGenerator.takeError(); 334 335 return Create(ObjLinkingLayer, PlatformJD, 336 std::move(*OrcRuntimeArchiveGenerator), 337 std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), 338 std::move(RuntimeAliases)); 339 } 340 341 Error MachOPlatform::setupJITDylib(JITDylib &JD) { 342 return setupJITDylib(JD, /*Opts=*/{}); 343 } 344 345 Error MachOPlatform::setupJITDylib(JITDylib &JD, HeaderOptions Opts) { 346 if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts)))) 347 return Err; 348 349 return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError(); 350 } 351 352 Error MachOPlatform::teardownJITDylib(JITDylib &JD) { 353 std::lock_guard<std::mutex> Lock(PlatformMutex); 354 auto I = JITDylibToHeaderAddr.find(&JD); 355 if (I != JITDylibToHeaderAddr.end()) { 356 assert(HeaderAddrToJITDylib.count(I->second) && 357 "HeaderAddrToJITDylib missing entry"); 358 HeaderAddrToJITDylib.erase(I->second); 359 JITDylibToHeaderAddr.erase(I); 360 } 361 JITDylibToPThreadKey.erase(&JD); 362 return Error::success(); 363 } 364 365 Error MachOPlatform::notifyAdding(ResourceTracker &RT, 366 const MaterializationUnit &MU) { 367 auto &JD = RT.getJITDylib(); 368 const auto &InitSym = MU.getInitializerSymbol(); 369 if (!InitSym) 370 return Error::success(); 371 372 RegisteredInitSymbols[&JD].add(InitSym, 373 SymbolLookupFlags::WeaklyReferencedSymbol); 374 LLVM_DEBUG({ 375 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU " 376 << MU.getName() << "\n"; 377 }); 378 return Error::success(); 379 } 380 381 Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { 382 llvm_unreachable("Not supported yet"); 383 } 384 385 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 386 ArrayRef<std::pair<const char *, const char *>> AL) { 387 for (auto &KV : AL) { 388 auto AliasName = ES.intern(KV.first); 389 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 390 Aliases[std::move(AliasName)] = {ES.intern(KV.second), 391 JITSymbolFlags::Exported}; 392 } 393 } 394 395 SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { 396 SymbolAliasMap Aliases; 397 addAliases(ES, Aliases, requiredCXXAliases()); 398 addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 399 addAliases(ES, Aliases, standardLazyCompilationAliases()); 400 return Aliases; 401 } 402 403 ArrayRef<std::pair<const char *, const char *>> 404 MachOPlatform::requiredCXXAliases() { 405 static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 406 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; 407 408 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 409 } 410 411 ArrayRef<std::pair<const char *, const char *>> 412 MachOPlatform::standardRuntimeUtilityAliases() { 413 static const std::pair<const char *, const char *> 414 StandardRuntimeUtilityAliases[] = { 415 {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, 416 {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"}, 417 {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"}, 418 {"___orc_rt_jit_dlupdate", "___orc_rt_macho_jit_dlupdate"}, 419 {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"}, 420 {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"}, 421 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; 422 423 return ArrayRef<std::pair<const char *, const char *>>( 424 StandardRuntimeUtilityAliases); 425 } 426 427 ArrayRef<std::pair<const char *, const char *>> 428 MachOPlatform::standardLazyCompilationAliases() { 429 static const std::pair<const char *, const char *> 430 StandardLazyCompilationAliases[] = { 431 {"__orc_rt_reenter", "__orc_rt_sysv_reenter"}, 432 {"__orc_rt_resolve_tag", "___orc_rt_resolve_tag"}}; 433 434 return ArrayRef<std::pair<const char *, const char *>>( 435 StandardLazyCompilationAliases); 436 } 437 438 bool MachOPlatform::supportedTarget(const Triple &TT) { 439 switch (TT.getArch()) { 440 case Triple::aarch64: 441 case Triple::x86_64: 442 return true; 443 default: 444 return false; 445 } 446 } 447 448 jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) { 449 switch (G.getTargetTriple().getArch()) { 450 case Triple::aarch64: 451 return jitlink::aarch64::Pointer64; 452 case Triple::x86_64: 453 return jitlink::x86_64::Pointer64; 454 default: 455 llvm_unreachable("Unsupported architecture"); 456 } 457 } 458 459 MachOPlatform::MachOExecutorSymbolFlags 460 MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) { 461 MachOPlatform::MachOExecutorSymbolFlags Flags{}; 462 if (Sym.getLinkage() == jitlink::Linkage::Weak) 463 Flags |= MachOExecutorSymbolFlags::Weak; 464 465 if (Sym.isCallable()) 466 Flags |= MachOExecutorSymbolFlags::Callable; 467 468 return Flags; 469 } 470 471 MachOPlatform::MachOPlatform( 472 ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, 473 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, 474 HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU, 475 Error &Err) 476 : ES(ObjLinkingLayer.getExecutionSession()), PlatformJD(PlatformJD), 477 ObjLinkingLayer(ObjLinkingLayer), 478 BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) { 479 ErrorAsOutParameter _(Err); 480 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this)); 481 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 482 483 BootstrapInfo BI; 484 Bootstrap = &BI; 485 486 // Bootstrap process -- here be phase-ordering dragons. 487 // 488 // The MachOPlatform class uses allocation actions to register metadata 489 // sections with the ORC runtime, however the runtime contains metadata 490 // registration functions that have their own metadata that they need to 491 // register (e.g. the frame-info registration functions have frame-info). 492 // We can't use an ordinary lookup to find these registration functions 493 // because their address is needed during the link of the containing graph 494 // itself (to build the allocation actions that will call the registration 495 // functions). Further complicating the situation (a) the graph containing 496 // the registration functions is allowed to depend on other graphs (e.g. the 497 // graph containing the ORC runtime RTTI support) so we need to handle an 498 // unknown set of dependencies during bootstrap, and (b) these graphs may 499 // be linked concurrently if the user has installed a concurrent dispatcher. 500 // 501 // We satisfy these constraints by implementing a bootstrap phase during which 502 // allocation actions generated by MachOPlatform are appended to a list of 503 // deferred allocation actions, rather than to the graphs themselves. At the 504 // end of the bootstrap process the deferred actions are attached to a final 505 // "complete-bootstrap" graph that causes them to be run. 506 // 507 // The bootstrap steps are as follows: 508 // 509 // 1. Request the graph containing the mach header. This graph is guaranteed 510 // not to have any metadata so the fact that the registration functions 511 // are not available yet is not a problem. 512 // 513 // 2. Look up the registration functions and discard the results. This will 514 // trigger linking of the graph containing these functions, and 515 // consequently any graphs that it depends on. We do not use the lookup 516 // result to find the addresses of the functions requested (as described 517 // above the lookup will return too late for that), instead we capture the 518 // addresses in a post-allocation pass injected by the platform runtime 519 // during bootstrap only. 520 // 521 // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of 522 // graphs being linked (potentially concurrently), and we block until all 523 // of these graphs have completed linking. This is to avoid a race on the 524 // deferred-actions vector: the lookup for the runtime registration 525 // functions may return while some functions (those that are being 526 // incidentally linked in, but aren't reachable via the runtime functions) 527 // are still being linked, and we need to capture any allocation actions 528 // for this incidental code before we proceed. 529 // 530 // 4. Once all active links are complete we transfer the deferred actions to 531 // a newly added CompleteBootstrap graph and then request a symbol from 532 // the CompleteBootstrap graph to trigger materialization. This will cause 533 // all deferred actions to be run, and once this lookup returns we can 534 // proceed. 535 // 536 // 5. Finally, we associate runtime support methods in MachOPlatform with 537 // the corresponding jit-dispatch tag variables in the ORC runtime to make 538 // the support methods callable. The bootstrap is now complete. 539 540 // Step (1) Add header materialization unit and request. 541 if ((Err = PlatformJD.define( 542 this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts))))) 543 return; 544 if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError())) 545 return; 546 547 // Step (2) Request runtime registration functions to trigger 548 // materialization.. 549 if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD), 550 SymbolLookupSet( 551 {PlatformBootstrap.Name, PlatformShutdown.Name, 552 RegisterJITDylib.Name, DeregisterJITDylib.Name, 553 RegisterObjectSymbolTable.Name, 554 DeregisterObjectSymbolTable.Name, 555 RegisterObjectPlatformSections.Name, 556 DeregisterObjectPlatformSections.Name, 557 CreatePThreadKey.Name})) 558 .takeError())) 559 return; 560 561 // Step (3) Wait for any incidental linker work to complete. 562 { 563 std::unique_lock<std::mutex> Lock(BI.Mutex); 564 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; }); 565 Bootstrap = nullptr; 566 } 567 568 // Step (4) Add complete-bootstrap materialization unit and request. 569 auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap"); 570 if ((Err = PlatformJD.define( 571 std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>( 572 *this, PlatformJD.getName(), BootstrapCompleteSymbol, 573 std::move(BI.SymTab), std::move(BI.DeferredAAs), 574 BI.MachOHeaderAddr, PlatformBootstrap.Addr, 575 PlatformShutdown.Addr, RegisterJITDylib.Addr, 576 DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr, 577 DeregisterObjectSymbolTable.Addr)))) 578 return; 579 if ((Err = ES.lookup(makeJITDylibSearchOrder( 580 &PlatformJD, JITDylibLookupFlags::MatchAllSymbols), 581 std::move(BootstrapCompleteSymbol)) 582 .takeError())) 583 return; 584 585 // (5) Associate runtime support functions. 586 // TODO: Consider moving this above (4) to make runtime support functions 587 // available to the bootstrap completion graph. We'd just need to be 588 // sure that the runtime support functions are fully usable before any 589 // bootstrap completion actions use them (e.g. the ORC runtime 590 // macho_platform object would have to have been created and 591 // initialized). 592 if ((Err = associateRuntimeSupportFunctions())) 593 return; 594 } 595 596 Error MachOPlatform::associateRuntimeSupportFunctions() { 597 ExecutionSession::JITDispatchHandlerAssociationMap WFs; 598 599 using PushInitializersSPSSig = 600 SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr); 601 WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] = 602 ES.wrapAsyncWithSPS<PushInitializersSPSSig>( 603 this, &MachOPlatform::rt_pushInitializers); 604 605 using PushSymbolsSPSSig = 606 SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>); 607 WFs[ES.intern("___orc_rt_macho_push_symbols_tag")] = 608 ES.wrapAsyncWithSPS<PushSymbolsSPSSig>(this, 609 &MachOPlatform::rt_pushSymbols); 610 611 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 612 } 613 614 void MachOPlatform::pushInitializersLoop( 615 PushInitializersSendResultFn SendResult, JITDylibSP JD) { 616 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 617 DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap; 618 SmallVector<JITDylib *, 16> Worklist({JD.get()}); 619 620 ES.runSessionLocked([&]() { 621 while (!Worklist.empty()) { 622 // FIXME: Check for defunct dylibs. 623 624 auto DepJD = Worklist.back(); 625 Worklist.pop_back(); 626 627 // If we've already visited this JITDylib on this iteration then continue. 628 if (JDDepMap.count(DepJD)) 629 continue; 630 631 // Add dep info. 632 auto &DM = JDDepMap[DepJD]; 633 DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) { 634 for (auto &KV : O) { 635 if (KV.first == DepJD) 636 continue; 637 DM.push_back(KV.first); 638 Worklist.push_back(KV.first); 639 } 640 }); 641 642 // Add any registered init symbols. 643 auto RISItr = RegisteredInitSymbols.find(DepJD); 644 if (RISItr != RegisteredInitSymbols.end()) { 645 NewInitSymbols[DepJD] = std::move(RISItr->second); 646 RegisteredInitSymbols.erase(RISItr); 647 } 648 } 649 }); 650 651 // If there are no further init symbols to look up then send the link order 652 // (as a list of header addresses) to the caller. 653 if (NewInitSymbols.empty()) { 654 655 // To make the list intelligible to the runtime we need to convert all 656 // JITDylib pointers to their header addresses. Only include JITDylibs 657 // that appear in the JITDylibToHeaderAddr map (i.e. those that have been 658 // through setupJITDylib) -- bare JITDylibs aren't managed by the platform. 659 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs; 660 HeaderAddrs.reserve(JDDepMap.size()); 661 { 662 std::lock_guard<std::mutex> Lock(PlatformMutex); 663 for (auto &KV : JDDepMap) { 664 auto I = JITDylibToHeaderAddr.find(KV.first); 665 if (I != JITDylibToHeaderAddr.end()) 666 HeaderAddrs[KV.first] = I->second; 667 } 668 } 669 670 // Build the dep info map to return. 671 MachOJITDylibDepInfoMap DIM; 672 DIM.reserve(JDDepMap.size()); 673 for (auto &KV : JDDepMap) { 674 auto HI = HeaderAddrs.find(KV.first); 675 // Skip unmanaged JITDylibs. 676 if (HI == HeaderAddrs.end()) 677 continue; 678 auto H = HI->second; 679 MachOJITDylibDepInfo DepInfo; 680 for (auto &Dep : KV.second) { 681 auto HJ = HeaderAddrs.find(Dep); 682 if (HJ != HeaderAddrs.end()) 683 DepInfo.DepHeaders.push_back(HJ->second); 684 } 685 DIM.push_back(std::make_pair(H, std::move(DepInfo))); 686 } 687 SendResult(DIM); 688 return; 689 } 690 691 // Otherwise issue a lookup and re-run this phase when it completes. 692 lookupInitSymbolsAsync( 693 [this, SendResult = std::move(SendResult), JD](Error Err) mutable { 694 if (Err) 695 SendResult(std::move(Err)); 696 else 697 pushInitializersLoop(std::move(SendResult), JD); 698 }, 699 ES, std::move(NewInitSymbols)); 700 } 701 702 void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult, 703 ExecutorAddr JDHeaderAddr) { 704 JITDylibSP JD; 705 { 706 std::lock_guard<std::mutex> Lock(PlatformMutex); 707 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr); 708 if (I != HeaderAddrToJITDylib.end()) 709 JD = I->second; 710 } 711 712 LLVM_DEBUG({ 713 dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") "; 714 if (JD) 715 dbgs() << "pushing initializers for " << JD->getName() << "\n"; 716 else 717 dbgs() << "No JITDylib for header address.\n"; 718 }); 719 720 if (!JD) { 721 SendResult(make_error<StringError>("No JITDylib with header addr " + 722 formatv("{0:x}", JDHeaderAddr), 723 inconvertibleErrorCode())); 724 return; 725 } 726 727 pushInitializersLoop(std::move(SendResult), JD); 728 } 729 730 void MachOPlatform::rt_pushSymbols( 731 PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle, 732 const std::vector<std::pair<StringRef, bool>> &SymbolNames) { 733 734 JITDylib *JD = nullptr; 735 736 { 737 std::lock_guard<std::mutex> Lock(PlatformMutex); 738 auto I = HeaderAddrToJITDylib.find(Handle); 739 if (I != HeaderAddrToJITDylib.end()) 740 JD = I->second; 741 } 742 LLVM_DEBUG({ 743 dbgs() << "MachOPlatform::rt_pushSymbols("; 744 if (JD) 745 dbgs() << "\"" << JD->getName() << "\", [ "; 746 else 747 dbgs() << "<invalid handle " << Handle << ">, [ "; 748 for (auto &Name : SymbolNames) 749 dbgs() << "\"" << Name.first << "\" "; 750 dbgs() << "])\n"; 751 }); 752 753 if (!JD) { 754 SendResult(make_error<StringError>("No JITDylib associated with handle " + 755 formatv("{0:x}", Handle), 756 inconvertibleErrorCode())); 757 return; 758 } 759 760 SymbolLookupSet LS; 761 for (auto &[Name, Required] : SymbolNames) 762 LS.add(ES.intern(Name), Required 763 ? SymbolLookupFlags::RequiredSymbol 764 : SymbolLookupFlags::WeaklyReferencedSymbol); 765 766 ES.lookup( 767 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 768 std::move(LS), SymbolState::Ready, 769 [SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable { 770 SendResult(Result.takeError()); 771 }, 772 NoDependenciesToRegister); 773 } 774 775 Expected<uint64_t> MachOPlatform::createPThreadKey() { 776 if (!CreatePThreadKey.Addr) 777 return make_error<StringError>( 778 "Attempting to create pthread key in target, but runtime support has " 779 "not been loaded yet", 780 inconvertibleErrorCode()); 781 782 Expected<uint64_t> Result(0); 783 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 784 CreatePThreadKey.Addr, Result)) 785 return std::move(Err); 786 return Result; 787 } 788 789 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 790 MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 791 jitlink::PassConfiguration &Config) { 792 793 using namespace jitlink; 794 795 bool InBootstrapPhase = false; 796 797 ExecutorAddr HeaderAddr; 798 { 799 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 800 if (LLVM_UNLIKELY(&MR.getTargetJITDylib() == &MP.PlatformJD)) { 801 if (MP.Bootstrap) { 802 InBootstrapPhase = true; 803 ++MP.Bootstrap->ActiveGraphs; 804 } 805 } 806 807 // Get the dso-base address if available. 808 auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib()); 809 if (I != MP.JITDylibToHeaderAddr.end()) 810 HeaderAddr = I->second; 811 } 812 813 // Point the libunwind dso-base absolute symbol at the header for the 814 // JITDylib. This will prevent us from synthesizing a new header for 815 // every object. 816 if (HeaderAddr) 817 LG.addAbsoluteSymbol("__jitlink$libunwind_dso_base", HeaderAddr, 0, 818 Linkage::Strong, Scope::Local, true); 819 820 // If we're in the bootstrap phase then increment the active graphs. 821 if (LLVM_UNLIKELY(InBootstrapPhase)) 822 Config.PostAllocationPasses.push_back([this](LinkGraph &G) { 823 return bootstrapPipelineRecordRuntimeFunctions(G); 824 }); 825 826 // --- Handle Initializers --- 827 if (auto InitSymbol = MR.getInitializerSymbol()) { 828 829 // If the initializer symbol is the MachOHeader start symbol then just 830 // register it and then bail out -- the header materialization unit 831 // definitely doesn't need any other passes. 832 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) { 833 Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) { 834 return associateJITDylibHeaderSymbol(G, MR); 835 }); 836 return; 837 } 838 839 // If the object contains an init symbol other than the header start symbol 840 // then add passes to preserve, process and register the init 841 // sections/symbols. 842 Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) { 843 if (auto Err = preserveImportantSections(G, MR)) 844 return Err; 845 return processObjCImageInfo(G, MR); 846 }); 847 Config.PostPrunePasses.push_back( 848 [this](LinkGraph &G) { return createObjCRuntimeObject(G); }); 849 Config.PostAllocationPasses.push_back( 850 [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); }); 851 } 852 853 // Insert TLV lowering at the start of the PostPrunePasses, since we want 854 // it to run before GOT/PLT lowering. 855 Config.PostPrunePasses.insert( 856 Config.PostPrunePasses.begin(), 857 [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) { 858 return fixTLVSectionsAndEdges(G, JD); 859 }); 860 861 // Add symbol table prepare and register passes: These will add strings for 862 // all symbols to the c-strings section, and build a symbol table registration 863 // call. 864 auto JITSymTabInfo = std::make_shared<JITSymTabVector>(); 865 Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) { 866 return prepareSymbolTableRegistration(G, *JITSymTabInfo); 867 }); 868 Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo, 869 InBootstrapPhase](LinkGraph &G) { 870 return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase); 871 }); 872 873 // Add a pass to register the final addresses of any special sections in the 874 // object with the runtime. 875 Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib(), 876 HeaderAddr, 877 InBootstrapPhase](LinkGraph &G) { 878 return registerObjectPlatformSections(G, JD, HeaderAddr, InBootstrapPhase); 879 }); 880 881 // If we're in the bootstrap phase then steal allocation actions and then 882 // decrement the active graphs. 883 if (InBootstrapPhase) 884 Config.PostFixupPasses.push_back( 885 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); }); 886 } 887 888 Error MachOPlatform::MachOPlatformPlugin:: 889 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) { 890 // Record bootstrap function names. 891 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = { 892 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap->MachOHeaderAddr}, 893 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr}, 894 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr}, 895 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr}, 896 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr}, 897 {*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr}, 898 {*MP.DeregisterObjectSymbolTable.Name, 899 &MP.DeregisterObjectSymbolTable.Addr}, 900 {*MP.RegisterObjectPlatformSections.Name, 901 &MP.RegisterObjectPlatformSections.Addr}, 902 {*MP.DeregisterObjectPlatformSections.Name, 903 &MP.DeregisterObjectPlatformSections.Addr}, 904 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}, 905 {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr}, 906 {*MP.DeregisterObjCRuntimeObject.Name, 907 &MP.DeregisterObjCRuntimeObject.Addr}}; 908 909 bool RegisterMachOHeader = false; 910 911 for (auto *Sym : G.defined_symbols()) { 912 for (auto &RTSym : RuntimeSymbols) { 913 if (Sym->hasName() && *Sym->getName() == RTSym.first) { 914 if (*RTSym.second) 915 return make_error<StringError>( 916 "Duplicate " + RTSym.first + 917 " detected during MachOPlatform bootstrap", 918 inconvertibleErrorCode()); 919 920 if (Sym->getName() == MP.MachOHeaderStartSymbol) 921 RegisterMachOHeader = true; 922 923 *RTSym.second = Sym->getAddress(); 924 } 925 } 926 } 927 928 if (RegisterMachOHeader) { 929 // If this graph defines the macho header symbol then create the internal 930 // mapping between it and PlatformJD. 931 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 932 MP.JITDylibToHeaderAddr[&MP.PlatformJD] = MP.Bootstrap->MachOHeaderAddr; 933 MP.HeaderAddrToJITDylib[MP.Bootstrap->MachOHeaderAddr] = &MP.PlatformJD; 934 } 935 936 return Error::success(); 937 } 938 939 Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd( 940 jitlink::LinkGraph &G) { 941 std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex); 942 943 --MP.Bootstrap->ActiveGraphs; 944 // Notify Bootstrap->CV while holding the mutex because the mutex is 945 // also keeping Bootstrap->CV alive. 946 if (MP.Bootstrap->ActiveGraphs == 0) 947 MP.Bootstrap->CV.notify_all(); 948 return Error::success(); 949 } 950 951 Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol( 952 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 953 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 954 return Sym->getName() == MP.MachOHeaderStartSymbol; 955 }); 956 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol"); 957 958 auto &JD = MR.getTargetJITDylib(); 959 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 960 auto HeaderAddr = (*I)->getAddress(); 961 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr; 962 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 963 // We can unconditionally add these actions to the Graph because this pass 964 // isn't used during bootstrap. 965 G.allocActions().push_back( 966 {cantFail( 967 WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>( 968 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)), 969 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 970 MP.DeregisterJITDylib.Addr, HeaderAddr))}); 971 return Error::success(); 972 } 973 974 Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections( 975 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 976 // __objc_imageinfo is "important": we want to preserve it and record its 977 // address in the first graph that it appears in, then verify and discard it 978 // in all subsequent graphs. In this pass we preserve unconditionally -- we'll 979 // manually throw it away in the processObjCImageInfo pass. 980 if (auto *ObjCImageInfoSec = 981 G.findSectionByName(MachOObjCImageInfoSectionName)) { 982 if (ObjCImageInfoSec->blocks_size() != 1) 983 return make_error<StringError>( 984 "In " + G.getName() + 985 "__DATA,__objc_imageinfo contains multiple blocks", 986 inconvertibleErrorCode()); 987 G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false, 988 true); 989 990 for (auto *B : ObjCImageInfoSec->blocks()) 991 if (!B->edges_empty()) 992 return make_error<StringError>("In " + G.getName() + ", " + 993 MachOObjCImageInfoSectionName + 994 " contains references to symbols", 995 inconvertibleErrorCode()); 996 } 997 998 // Init sections are important: We need to preserve them and so that their 999 // addresses can be captured and reported to the ORC runtime in 1000 // registerObjectPlatformSections. 1001 if (const auto &InitSymName = MR.getInitializerSymbol()) { 1002 1003 jitlink::Symbol *InitSym = nullptr; 1004 for (auto &InitSectionName : MachOInitSectionNames) { 1005 // Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may 1006 // remove it later. 1007 if (InitSectionName == MachOObjCImageInfoSectionName) 1008 continue; 1009 1010 // Skip non-init sections. 1011 auto *InitSection = G.findSectionByName(InitSectionName); 1012 if (!InitSection || InitSection->empty()) 1013 continue; 1014 1015 // Create the init symbol if it has not been created already and attach it 1016 // to the first block. 1017 if (!InitSym) { 1018 auto &B = **InitSection->blocks().begin(); 1019 InitSym = &G.addDefinedSymbol( 1020 B, 0, *InitSymName, B.getSize(), jitlink::Linkage::Strong, 1021 jitlink::Scope::SideEffectsOnly, false, true); 1022 } 1023 1024 // Add keep-alive edges to anonymous symbols in all other init blocks. 1025 for (auto *B : InitSection->blocks()) { 1026 if (B == &InitSym->getBlock()) 1027 continue; 1028 1029 auto &S = G.addAnonymousSymbol(*B, 0, B->getSize(), false, true); 1030 InitSym->getBlock().addEdge(jitlink::Edge::KeepAlive, 0, S, 0); 1031 } 1032 } 1033 } 1034 1035 return Error::success(); 1036 } 1037 1038 Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo( 1039 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 1040 1041 // If there's an ObjC imagine info then either 1042 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In 1043 // this case we name and record it. 1044 // OR 1045 // (2) We already have a recorded __objc_imageinfo for this JITDylib, 1046 // in which case we just verify it. 1047 auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName); 1048 if (!ObjCImageInfo) 1049 return Error::success(); 1050 1051 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); 1052 1053 // Check that the section is not empty if present. 1054 if (ObjCImageInfoBlocks.empty()) 1055 return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName + 1056 " section in " + G.getName(), 1057 inconvertibleErrorCode()); 1058 1059 // Check that there's only one block in the section. 1060 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) 1061 return make_error<StringError>("Multiple blocks in " + 1062 MachOObjCImageInfoSectionName + 1063 " section in " + G.getName(), 1064 inconvertibleErrorCode()); 1065 1066 // Check that the __objc_imageinfo section is unreferenced. 1067 // FIXME: We could optimize this check if Symbols had a ref-count. 1068 for (auto &Sec : G.sections()) { 1069 if (&Sec != ObjCImageInfo) 1070 for (auto *B : Sec.blocks()) 1071 for (auto &E : B->edges()) 1072 if (E.getTarget().isDefined() && 1073 &E.getTarget().getBlock().getSection() == ObjCImageInfo) 1074 return make_error<StringError>(MachOObjCImageInfoSectionName + 1075 " is referenced within file " + 1076 G.getName(), 1077 inconvertibleErrorCode()); 1078 } 1079 1080 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); 1081 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); 1082 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); 1083 auto Flags = 1084 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); 1085 1086 // Lock the mutex while we verify / update the ObjCImageInfos map. 1087 std::lock_guard<std::mutex> Lock(PluginMutex); 1088 1089 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); 1090 if (ObjCImageInfoItr != ObjCImageInfos.end()) { 1091 // We've already registered an __objc_imageinfo section. Verify the 1092 // content of this new section matches, then delete it. 1093 if (ObjCImageInfoItr->second.Version != Version) 1094 return make_error<StringError>( 1095 "ObjC version in " + G.getName() + 1096 " does not match first registered version", 1097 inconvertibleErrorCode()); 1098 if (ObjCImageInfoItr->second.Flags != Flags) 1099 if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags)) 1100 return E; 1101 1102 // __objc_imageinfo is valid. Delete the block. 1103 for (auto *S : ObjCImageInfo->symbols()) 1104 G.removeDefinedSymbol(*S); 1105 G.removeBlock(ObjCImageInfoBlock); 1106 } else { 1107 LLVM_DEBUG({ 1108 dbgs() << "MachOPlatform: Registered __objc_imageinfo for " 1109 << MR.getTargetJITDylib().getName() << " in " << G.getName() 1110 << "; flags = " << formatv("{0:x4}", Flags) << "\n"; 1111 }); 1112 // We haven't registered an __objc_imageinfo section yet. Register and 1113 // move on. The section should already be marked no-dead-strip. 1114 G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName, 1115 ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong, 1116 jitlink::Scope::Hidden, false, true); 1117 if (auto Err = MR.defineMaterializing( 1118 {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName), 1119 JITSymbolFlags()}})) 1120 return Err; 1121 ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags, false}; 1122 } 1123 1124 return Error::success(); 1125 } 1126 1127 Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags( 1128 jitlink::LinkGraph &G, MaterializationResponsibility &MR, 1129 ObjCImageInfo &Info, uint32_t NewFlags) { 1130 if (Info.Flags == NewFlags) 1131 return Error::success(); 1132 1133 ObjCImageInfoFlags Old(Info.Flags); 1134 ObjCImageInfoFlags New(NewFlags); 1135 1136 // Check for incompatible flags. 1137 if (Old.SwiftABIVersion && New.SwiftABIVersion && 1138 Old.SwiftABIVersion != New.SwiftABIVersion) 1139 return make_error<StringError>("Swift ABI version in " + G.getName() + 1140 " does not match first registered flags", 1141 inconvertibleErrorCode()); 1142 1143 // HasCategoryClassProperties and HasSignedObjCClassROs can be disabled before 1144 // they are registered, if necessary, but once they are in use must be 1145 // supported by subsequent objects. 1146 if (Info.Finalized && Old.HasCategoryClassProperties && 1147 !New.HasCategoryClassProperties) 1148 return make_error<StringError>("ObjC category class property support in " + 1149 G.getName() + 1150 " does not match first registered flags", 1151 inconvertibleErrorCode()); 1152 if (Info.Finalized && Old.HasSignedObjCClassROs && !New.HasSignedObjCClassROs) 1153 return make_error<StringError>("ObjC class_ro_t pointer signing in " + 1154 G.getName() + 1155 " does not match first registered flags", 1156 inconvertibleErrorCode()); 1157 1158 // If we cannot change the flags, ignore any remaining differences. Adding 1159 // Swift or changing its version are unlikely to cause problems in practice. 1160 if (Info.Finalized) 1161 return Error::success(); 1162 1163 // Use the minimum Swift version. 1164 if (Old.SwiftVersion && New.SwiftVersion) 1165 New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion); 1166 else if (Old.SwiftVersion) 1167 New.SwiftVersion = Old.SwiftVersion; 1168 // Add a Swift ABI version if it was pure objc before. 1169 if (!New.SwiftABIVersion) 1170 New.SwiftABIVersion = Old.SwiftABIVersion; 1171 // Disable class properties if any object does not support it. 1172 if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties) 1173 New.HasCategoryClassProperties = false; 1174 // Disable signed class ro data if any object does not support it. 1175 if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs) 1176 New.HasSignedObjCClassROs = false; 1177 1178 LLVM_DEBUG({ 1179 dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for " 1180 << MR.getTargetJITDylib().getName() << " (was " 1181 << formatv("{0:x4}", Old.rawFlags()) << ")" 1182 << " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags) 1183 << ")" 1184 << " -> " << formatv("{0:x4}", New.rawFlags()) << "\n"; 1185 }); 1186 1187 Info.Flags = New.rawFlags(); 1188 return Error::success(); 1189 } 1190 1191 Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges( 1192 jitlink::LinkGraph &G, JITDylib &JD) { 1193 auto TLVBootStrapSymbolName = G.intern("__tlv_bootstrap"); 1194 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr. 1195 for (auto *Sym : G.external_symbols()) 1196 if (Sym->getName() == TLVBootStrapSymbolName) { 1197 auto TLSGetADDR = 1198 MP.getExecutionSession().intern("___orc_rt_macho_tlv_get_addr"); 1199 Sym->setName(std::move(TLSGetADDR)); 1200 break; 1201 } 1202 1203 // Store key in __thread_vars struct fields. 1204 if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) { 1205 std::optional<uint64_t> Key; 1206 { 1207 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 1208 auto I = MP.JITDylibToPThreadKey.find(&JD); 1209 if (I != MP.JITDylibToPThreadKey.end()) 1210 Key = I->second; 1211 } 1212 1213 if (!Key) { 1214 if (auto KeyOrErr = MP.createPThreadKey()) 1215 Key = *KeyOrErr; 1216 else 1217 return KeyOrErr.takeError(); 1218 } 1219 1220 uint64_t PlatformKeyBits = 1221 support::endian::byte_swap(*Key, G.getEndianness()); 1222 1223 for (auto *B : ThreadDataSec->blocks()) { 1224 if (B->getSize() != 3 * G.getPointerSize()) 1225 return make_error<StringError>("__thread_vars block at " + 1226 formatv("{0:x}", B->getAddress()) + 1227 " has unexpected size", 1228 inconvertibleErrorCode()); 1229 1230 auto NewBlockContent = G.allocateBuffer(B->getSize()); 1231 llvm::copy(B->getContent(), NewBlockContent.data()); 1232 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits, 1233 G.getPointerSize()); 1234 B->setContent(NewBlockContent); 1235 } 1236 } 1237 1238 // Transform any TLV edges into GOT edges. 1239 for (auto *B : G.blocks()) 1240 for (auto &E : B->edges()) 1241 if (E.getKind() == 1242 jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable) 1243 E.setKind(jitlink::x86_64:: 1244 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable); 1245 1246 return Error::success(); 1247 } 1248 1249 std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections> 1250 MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo( 1251 jitlink::LinkGraph &G) { 1252 using namespace jitlink; 1253 1254 UnwindSections US; 1255 1256 // ScanSection records a section range and adds any executable blocks that 1257 // that section points to to the CodeBlocks vector. 1258 SmallVector<Block *> CodeBlocks; 1259 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) { 1260 if (Sec.blocks().empty()) 1261 return; 1262 SecRange = (*Sec.blocks().begin())->getRange(); 1263 for (auto *B : Sec.blocks()) { 1264 auto R = B->getRange(); 1265 SecRange.Start = std::min(SecRange.Start, R.Start); 1266 SecRange.End = std::max(SecRange.End, R.End); 1267 for (auto &E : B->edges()) { 1268 if (E.getKind() != Edge::KeepAlive || !E.getTarget().isDefined()) 1269 continue; 1270 auto &TargetBlock = E.getTarget().getBlock(); 1271 auto &TargetSection = TargetBlock.getSection(); 1272 if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec) 1273 CodeBlocks.push_back(&TargetBlock); 1274 } 1275 } 1276 }; 1277 1278 if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) 1279 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection); 1280 1281 if (Section *CUInfoSec = 1282 G.findSectionByName(MachOCompactUnwindInfoSectionName)) 1283 ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection); 1284 1285 // If we didn't find any pointed-to code-blocks then there's no need to 1286 // register any info. 1287 if (CodeBlocks.empty()) 1288 return std::nullopt; 1289 1290 // We have info to register. Sort the code blocks into address order and 1291 // build a list of contiguous address ranges covering them all. 1292 llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) { 1293 return LHS->getAddress() < RHS->getAddress(); 1294 }); 1295 for (auto *B : CodeBlocks) { 1296 if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress()) 1297 US.CodeRanges.push_back(B->getRange()); 1298 else 1299 US.CodeRanges.back().End = B->getRange().End; 1300 } 1301 1302 LLVM_DEBUG({ 1303 dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n" 1304 << " DWARF: "; 1305 if (US.DwarfSection.Start) 1306 dbgs() << US.DwarfSection << "\n"; 1307 else 1308 dbgs() << "none\n"; 1309 dbgs() << " Compact-unwind: "; 1310 if (US.CompactUnwindSection.Start) 1311 dbgs() << US.CompactUnwindSection << "\n"; 1312 else 1313 dbgs() << "none\n" 1314 << "for code ranges:\n"; 1315 for (auto &CR : US.CodeRanges) 1316 dbgs() << " " << CR << "\n"; 1317 if (US.CodeRanges.size() >= G.sections_size()) 1318 dbgs() << "WARNING: High number of discontiguous code ranges! " 1319 "Padding may be interfering with coalescing.\n"; 1320 }); 1321 1322 return US; 1323 } 1324 1325 Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections( 1326 jitlink::LinkGraph &G, JITDylib &JD, ExecutorAddr HeaderAddr, 1327 bool InBootstrapPhase) { 1328 1329 // Get a pointer to the thread data section if there is one. It will be used 1330 // below. 1331 jitlink::Section *ThreadDataSection = 1332 G.findSectionByName(MachOThreadDataSectionName); 1333 1334 // Handle thread BSS section if there is one. 1335 if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) { 1336 // If there's already a thread data section in this graph then merge the 1337 // thread BSS section content into it, otherwise just treat the thread 1338 // BSS section as the thread data section. 1339 if (ThreadDataSection) 1340 G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 1341 else 1342 ThreadDataSection = ThreadBSSSection; 1343 } 1344 1345 SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs; 1346 1347 // Collect data sections to register. 1348 StringRef DataSections[] = {MachODataDataSectionName, 1349 MachODataCommonSectionName, 1350 MachOEHFrameSectionName}; 1351 for (auto &SecName : DataSections) { 1352 if (auto *Sec = G.findSectionByName(SecName)) { 1353 jitlink::SectionRange R(*Sec); 1354 if (!R.empty()) 1355 MachOPlatformSecs.push_back({SecName, R.getRange()}); 1356 } 1357 } 1358 1359 // Having merged thread BSS (if present) and thread data (if present), 1360 // record the resulting section range. 1361 if (ThreadDataSection) { 1362 jitlink::SectionRange R(*ThreadDataSection); 1363 if (!R.empty()) 1364 MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()}); 1365 } 1366 1367 // If any platform sections were found then add an allocation action to call 1368 // the registration function. 1369 StringRef PlatformSections[] = {MachOModInitFuncSectionName, 1370 ObjCRuntimeObjectSectionName}; 1371 1372 for (auto &SecName : PlatformSections) { 1373 auto *Sec = G.findSectionByName(SecName); 1374 if (!Sec) 1375 continue; 1376 jitlink::SectionRange R(*Sec); 1377 if (R.empty()) 1378 continue; 1379 1380 MachOPlatformSecs.push_back({SecName, R.getRange()}); 1381 } 1382 1383 std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange, 1384 ExecutorAddrRange>> 1385 UnwindInfo; 1386 if (auto UI = findUnwindSectionInfo(G)) 1387 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection, 1388 UI->CompactUnwindSection); 1389 1390 if (!MachOPlatformSecs.empty() || UnwindInfo) { 1391 // Dump the scraped inits. 1392 LLVM_DEBUG({ 1393 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 1394 for (auto &KV : MachOPlatformSecs) 1395 dbgs() << " " << KV.first << ": " << KV.second << "\n"; 1396 }); 1397 1398 assert(HeaderAddr && "Null header registered for JD"); 1399 using SPSRegisterObjectPlatformSectionsArgs = SPSArgList< 1400 SPSExecutorAddr, 1401 SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>, 1402 SPSExecutorAddrRange, SPSExecutorAddrRange>>, 1403 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>; 1404 1405 AllocActionCallPair AllocActions = { 1406 cantFail( 1407 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1408 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo, 1409 MachOPlatformSecs)), 1410 cantFail( 1411 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1412 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr, 1413 UnwindInfo, MachOPlatformSecs))}; 1414 1415 if (LLVM_LIKELY(!InBootstrapPhase)) 1416 G.allocActions().push_back(std::move(AllocActions)); 1417 else { 1418 std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex); 1419 MP.Bootstrap->DeferredAAs.push_back(std::move(AllocActions)); 1420 } 1421 } 1422 1423 return Error::success(); 1424 } 1425 1426 Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject( 1427 jitlink::LinkGraph &G) { 1428 1429 bool NeedTextSegment = false; 1430 size_t NumRuntimeSections = 0; 1431 1432 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) 1433 if (G.findSectionByName(ObjCRuntimeSectionName)) 1434 ++NumRuntimeSections; 1435 1436 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 1437 if (G.findSectionByName(ObjCRuntimeSectionName)) { 1438 ++NumRuntimeSections; 1439 NeedTextSegment = true; 1440 } 1441 } 1442 1443 // Early out for no runtime sections. 1444 if (NumRuntimeSections == 0) 1445 return Error::success(); 1446 1447 // If there were any runtime sections then we need to add an __objc_imageinfo 1448 // section. 1449 ++NumRuntimeSections; 1450 1451 size_t MachOSize = sizeof(MachO::mach_header_64) + 1452 (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) + 1453 NumRuntimeSections * sizeof(MachO::section_64); 1454 1455 auto &Sec = G.createSection(ObjCRuntimeObjectSectionName, 1456 MemProt::Read | MemProt::Write); 1457 G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true); 1458 1459 return Error::success(); 1460 } 1461 1462 Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject( 1463 jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 1464 1465 auto *ObjCRuntimeObjectSec = 1466 G.findSectionByName(ObjCRuntimeObjectSectionName); 1467 1468 if (!ObjCRuntimeObjectSec) 1469 return Error::success(); 1470 1471 switch (G.getTargetTriple().getArch()) { 1472 case Triple::aarch64: 1473 case Triple::x86_64: 1474 // Supported. 1475 break; 1476 default: 1477 return make_error<StringError>("Unrecognized MachO arch in triple " + 1478 G.getTargetTriple().str(), 1479 inconvertibleErrorCode()); 1480 } 1481 1482 auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin(); 1483 1484 struct SecDesc { 1485 MachO::section_64 Sec; 1486 unique_function<void(size_t RecordOffset)> AddFixups; 1487 }; 1488 1489 std::vector<SecDesc> TextSections, DataSections; 1490 auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) { 1491 jitlink::SectionRange SR(GraphSec); 1492 StringRef FQName = GraphSec.getName(); 1493 memset(&SD.Sec, 0, sizeof(MachO::section_64)); 1494 memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7); 1495 memcpy(SD.Sec.segname, FQName.data(), 6); 1496 SD.Sec.addr = SR.getStart() - SecBlock.getAddress(); 1497 SD.Sec.size = SR.getSize(); 1498 SD.Sec.flags = MachO::S_REGULAR; 1499 }; 1500 1501 // Add the __objc_imageinfo section. 1502 { 1503 DataSections.push_back({}); 1504 auto &SD = DataSections.back(); 1505 memset(&SD.Sec, 0, sizeof(SD.Sec)); 1506 memcpy(SD.Sec.sectname, "__objc_imageinfo", 16); 1507 strcpy(SD.Sec.segname, "__DATA"); 1508 SD.Sec.size = 8; 1509 jitlink::Symbol *ObjCImageInfoSym = nullptr; 1510 SD.AddFixups = [&, ObjCImageInfoSym](size_t RecordOffset) mutable { 1511 auto PointerEdge = getPointerEdgeKind(G); 1512 1513 // Look for an existing __objc_imageinfo symbol. 1514 if (!ObjCImageInfoSym) { 1515 auto Name = G.intern(ObjCImageInfoSymbolName); 1516 ObjCImageInfoSym = G.findExternalSymbolByName(Name); 1517 if (!ObjCImageInfoSym) 1518 ObjCImageInfoSym = G.findAbsoluteSymbolByName(Name); 1519 if (!ObjCImageInfoSym) { 1520 ObjCImageInfoSym = G.findDefinedSymbolByName(Name); 1521 if (ObjCImageInfoSym) { 1522 std::optional<uint32_t> Flags; 1523 { 1524 std::lock_guard<std::mutex> Lock(PluginMutex); 1525 auto It = ObjCImageInfos.find(&MR.getTargetJITDylib()); 1526 if (It != ObjCImageInfos.end()) { 1527 It->second.Finalized = true; 1528 Flags = It->second.Flags; 1529 } 1530 } 1531 1532 if (Flags) { 1533 // We own the definition of __objc_image_info; write the final 1534 // merged flags value. 1535 auto Content = ObjCImageInfoSym->getBlock().getMutableContent(G); 1536 assert( 1537 Content.size() == 8 && 1538 "__objc_image_info size should have been verified already"); 1539 support::endian::write32(&Content[4], *Flags, G.getEndianness()); 1540 } 1541 } 1542 } 1543 if (!ObjCImageInfoSym) 1544 ObjCImageInfoSym = &G.addExternalSymbol(std::move(Name), 8, false); 1545 } 1546 1547 SecBlock.addEdge(PointerEdge, 1548 RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec), 1549 *ObjCImageInfoSym, -SecBlock.getAddress().getValue()); 1550 }; 1551 } 1552 1553 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) { 1554 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 1555 DataSections.push_back({}); 1556 AddSection(DataSections.back(), *GraphSec); 1557 } 1558 } 1559 1560 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 1561 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 1562 TextSections.push_back({}); 1563 AddSection(TextSections.back(), *GraphSec); 1564 } 1565 } 1566 1567 assert(ObjCRuntimeObjectSec->blocks_size() == 1 && 1568 "Unexpected number of blocks in runtime sections object"); 1569 1570 // Build the header struct up-front. This also gives us a chance to check 1571 // that the triple is supported, which we'll assume below. 1572 MachO::mach_header_64 Hdr; 1573 Hdr.magic = MachO::MH_MAGIC_64; 1574 switch (G.getTargetTriple().getArch()) { 1575 case Triple::aarch64: 1576 Hdr.cputype = MachO::CPU_TYPE_ARM64; 1577 Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 1578 break; 1579 case Triple::x86_64: 1580 Hdr.cputype = MachO::CPU_TYPE_X86_64; 1581 Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 1582 break; 1583 default: 1584 llvm_unreachable("Unsupported architecture"); 1585 } 1586 1587 Hdr.filetype = MachO::MH_DYLIB; 1588 Hdr.ncmds = 1 + !TextSections.empty(); 1589 Hdr.sizeofcmds = 1590 Hdr.ncmds * sizeof(MachO::segment_command_64) + 1591 (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64); 1592 Hdr.flags = 0; 1593 Hdr.reserved = 0; 1594 1595 auto SecContent = SecBlock.getAlreadyMutableContent(); 1596 char *P = SecContent.data(); 1597 auto WriteMachOStruct = [&](auto S) { 1598 if (G.getEndianness() != llvm::endianness::native) 1599 MachO::swapStruct(S); 1600 memcpy(P, &S, sizeof(S)); 1601 P += sizeof(S); 1602 }; 1603 1604 auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) { 1605 MachO::segment_command_64 SegLC; 1606 memset(&SegLC, 0, sizeof(SegLC)); 1607 memcpy(SegLC.segname, Name.data(), Name.size()); 1608 SegLC.cmd = MachO::LC_SEGMENT_64; 1609 SegLC.cmdsize = sizeof(MachO::segment_command_64) + 1610 Secs.size() * sizeof(MachO::section_64); 1611 SegLC.nsects = Secs.size(); 1612 WriteMachOStruct(SegLC); 1613 for (auto &SD : Secs) { 1614 if (SD.AddFixups) 1615 SD.AddFixups(P - SecContent.data()); 1616 WriteMachOStruct(SD.Sec); 1617 } 1618 }; 1619 1620 WriteMachOStruct(Hdr); 1621 if (!TextSections.empty()) 1622 WriteSegment("__TEXT", TextSections); 1623 if (!DataSections.empty()) 1624 WriteSegment("__DATA", DataSections); 1625 1626 assert(P == SecContent.end() && "Underflow writing ObjC runtime object"); 1627 return Error::success(); 1628 } 1629 1630 Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration( 1631 jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) { 1632 1633 auto *CStringSec = G.findSectionByName(MachOCStringSectionName); 1634 if (!CStringSec) 1635 CStringSec = &G.createSection(MachOCStringSectionName, 1636 MemProt::Read | MemProt::Exec); 1637 1638 // Make a map of existing strings so that we can re-use them: 1639 DenseMap<StringRef, jitlink::Symbol *> ExistingStrings; 1640 for (auto *Sym : CStringSec->symbols()) { 1641 1642 // The LinkGraph builder should have created single strings blocks, and all 1643 // plugins should have maintained this invariant. 1644 auto Content = Sym->getBlock().getContent(); 1645 ExistingStrings.insert( 1646 std::make_pair(StringRef(Content.data(), Content.size()), Sym)); 1647 } 1648 1649 // Add all symbol names to the string section, and record the symbols for 1650 // those names. 1651 { 1652 SmallVector<jitlink::Symbol *> SymsToProcess; 1653 for (auto *Sym : G.defined_symbols()) 1654 SymsToProcess.push_back(Sym); 1655 for (auto *Sym : G.absolute_symbols()) 1656 SymsToProcess.push_back(Sym); 1657 1658 for (auto *Sym : SymsToProcess) { 1659 if (!Sym->hasName()) 1660 continue; 1661 1662 auto I = ExistingStrings.find(*Sym->getName()); 1663 if (I == ExistingStrings.end()) { 1664 auto &NameBlock = G.createMutableContentBlock( 1665 *CStringSec, G.allocateCString(*Sym->getName()), 1666 orc::ExecutorAddr(), 1, 0); 1667 auto &SymbolNameSym = G.addAnonymousSymbol( 1668 NameBlock, 0, NameBlock.getSize(), false, true); 1669 JITSymTabInfo.push_back({Sym, &SymbolNameSym}); 1670 } else 1671 JITSymTabInfo.push_back({Sym, I->second}); 1672 } 1673 } 1674 1675 return Error::success(); 1676 } 1677 1678 Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration( 1679 jitlink::LinkGraph &G, MaterializationResponsibility &MR, 1680 JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) { 1681 1682 ExecutorAddr HeaderAddr; 1683 { 1684 std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 1685 auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib()); 1686 assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD"); 1687 assert(I->second && "Null header registered for JD"); 1688 HeaderAddr = I->second; 1689 } 1690 1691 if (LLVM_UNLIKELY(InBootstrapPhase)) { 1692 // If we're in the bootstrap phase then just record these symbols in the 1693 // bootstrap object and then bail out -- registration will be attached to 1694 // the bootstrap graph. 1695 std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex); 1696 auto &SymTab = MP.Bootstrap->SymTab; 1697 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo) 1698 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(), 1699 flagsForSymbol(*OriginalSymbol)}); 1700 return Error::success(); 1701 } 1702 1703 SymbolTableVector SymTab; 1704 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo) 1705 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(), 1706 flagsForSymbol(*OriginalSymbol)}); 1707 1708 G.allocActions().push_back( 1709 {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 1710 MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)), 1711 cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 1712 MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))}); 1713 1714 return Error::success(); 1715 } 1716 1717 template <typename MachOTraits> 1718 jitlink::Block &createHeaderBlock(MachOPlatform &MOP, 1719 const MachOPlatform::HeaderOptions &Opts, 1720 JITDylib &JD, jitlink::LinkGraph &G, 1721 jitlink::Section &HeaderSection) { 1722 auto HdrInfo = 1723 getMachOHeaderInfoFromTriple(MOP.getExecutionSession().getTargetTriple()); 1724 MachOBuilder<MachOTraits> B(HdrInfo.PageSize); 1725 1726 B.Header.filetype = MachO::MH_DYLIB; 1727 B.Header.cputype = HdrInfo.CPUType; 1728 B.Header.cpusubtype = HdrInfo.CPUSubType; 1729 1730 if (Opts.IDDylib) 1731 B.template addLoadCommand<MachO::LC_ID_DYLIB>( 1732 Opts.IDDylib->Name, Opts.IDDylib->Timestamp, 1733 Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion); 1734 else 1735 B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0); 1736 1737 for (auto &BV : Opts.BuildVersions) 1738 B.template addLoadCommand<MachO::LC_BUILD_VERSION>( 1739 BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0)); 1740 for (auto &D : Opts.LoadDylibs) 1741 B.template addLoadCommand<MachO::LC_LOAD_DYLIB>( 1742 D.Name, D.Timestamp, D.CurrentVersion, D.CompatibilityVersion); 1743 for (auto &P : Opts.RPaths) 1744 B.template addLoadCommand<MachO::LC_RPATH>(P); 1745 1746 auto HeaderContent = G.allocateBuffer(B.layout()); 1747 B.write(HeaderContent); 1748 1749 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8, 1750 0); 1751 } 1752 1753 SimpleMachOHeaderMU::SimpleMachOHeaderMU(MachOPlatform &MOP, 1754 SymbolStringPtr HeaderStartSymbol, 1755 MachOPlatform::HeaderOptions Opts) 1756 : MaterializationUnit( 1757 createHeaderInterface(MOP, std::move(HeaderStartSymbol))), 1758 MOP(MOP), Opts(std::move(Opts)) {} 1759 1760 void SimpleMachOHeaderMU::materialize( 1761 std::unique_ptr<MaterializationResponsibility> R) { 1762 auto G = createPlatformGraph(MOP, "<MachOHeaderMU>"); 1763 addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol()); 1764 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 1765 } 1766 1767 void SimpleMachOHeaderMU::discard(const JITDylib &JD, 1768 const SymbolStringPtr &Sym) {} 1769 1770 void SimpleMachOHeaderMU::addMachOHeader( 1771 JITDylib &JD, jitlink::LinkGraph &G, 1772 const SymbolStringPtr &InitializerSymbol) { 1773 auto &HeaderSection = G.createSection("__header", MemProt::Read); 1774 auto &HeaderBlock = createHeaderBlock(JD, G, HeaderSection); 1775 1776 // Init symbol is header-start symbol. 1777 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(), 1778 jitlink::Linkage::Strong, jitlink::Scope::Default, false, 1779 true); 1780 for (auto &HS : AdditionalHeaderSymbols) 1781 G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(), 1782 jitlink::Linkage::Strong, jitlink::Scope::Default, false, 1783 true); 1784 } 1785 1786 jitlink::Block & 1787 SimpleMachOHeaderMU::createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G, 1788 jitlink::Section &HeaderSection) { 1789 switch (MOP.getExecutionSession().getTargetTriple().getArch()) { 1790 case Triple::aarch64: 1791 case Triple::x86_64: 1792 return ::createHeaderBlock<MachO64LE>(MOP, Opts, JD, G, HeaderSection); 1793 default: 1794 llvm_unreachable("Unsupported architecture"); 1795 } 1796 } 1797 1798 MaterializationUnit::Interface SimpleMachOHeaderMU::createHeaderInterface( 1799 MachOPlatform &MOP, const SymbolStringPtr &HeaderStartSymbol) { 1800 SymbolFlagsMap HeaderSymbolFlags; 1801 1802 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 1803 for (auto &HS : AdditionalHeaderSymbols) 1804 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = 1805 JITSymbolFlags::Exported; 1806 1807 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags), 1808 HeaderStartSymbol); 1809 } 1810 1811 MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT) { 1812 switch (TT.getArch()) { 1813 case Triple::aarch64: 1814 return {/* PageSize = */ 16 * 1024, 1815 /* CPUType = */ MachO::CPU_TYPE_ARM64, 1816 /* CPUSubType = */ MachO::CPU_SUBTYPE_ARM64_ALL}; 1817 case Triple::x86_64: 1818 return {/* PageSize = */ 4 * 1024, 1819 /* CPUType = */ MachO::CPU_TYPE_X86_64, 1820 /* CPUSubType = */ MachO::CPU_SUBTYPE_X86_64_ALL}; 1821 default: 1822 llvm_unreachable("Unrecognized architecture"); 1823 } 1824 } 1825 1826 } // End namespace orc. 1827 } // End namespace llvm. 1828