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