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