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