Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

ランタイムライブラリのbackward-deploymentの仕組み

Yuta Saito
September 24, 2021

 ランタイムライブラリのbackward-deploymentの仕組み

[わいわいswiftc #30 オンライン - connpass](https://iosdiscord.connpass.com/event/223396/)

Yuta Saito

September 24, 2021
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

  1. ABI Stability͕Մೳʹ͢Δ͜ͱ ྫ • Swift 5.0ͰίϯύΠϧͨ͠ϥΠϒϥϦ͕ɺ Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦͰ࢖͑Δɻ • Swift

    5.0ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ Swift 5.1ͷϥϯλΠϜͰಈ͘ɻ • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ Swift 5.0ͷϥϯλΠϜͰಈ͘ɻ 9
  2. ABI Stabilizeલ (~ Swift 5.0) • ֤ΞϓϦ͕ϥϯλΠϜϥΠϒϥϦΛಉࠝ • ΞϓϦͱϥϯλΠϜͷݴޠόʔδϣϯ͕ৗʹҰக ./My.app

    ├── Frameworks │ └── libswiftCore.dylib ├── Info.plist ├── My └── _CodeSignature 10
  3. ABI Stabilizeલ (Swift 5.0 ~) • iOS 13ɺmacOS 10.14.4 ͔ΒOSࣗମʹಉࠝ

    • ϥΠϒϥϦΛల։͢ΔϝϞϦΛΞϓϦؒͰڞ༗ • ΞϓϦͷόϯυϧαΠζ΋ݮͬͯخ͍͠ • ͕ɺϥϯλΠϜͷόʔδϣϯ͕OS͝ͱʹݻఆ͞Εͯ͠·ͬͨ 11
  4. ϥϯλΠϜ͕OSʹೖΔ͜ͱͰى͜Δ໰୊ ΞϓϦ͕࢖͏ݴޠόʔδϣϯͱϥϯλΠϜόʔδϣϯ͕ඞͣ͠ ΋Ұக͠ͳ͍ ྫ • Swift 5.0ͰίϯύΠϧͨ͠ΞϓϦΛɺ Swift 5.1ͷϥϯλΠϜͰಈ͔͢ɻ ->

    ϥϯλΠϜͷޙํޓ׵ੑ • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦΛɺ Swift 5.0ͷϥϯλΠϜͰಈ͔͢ɻ -> ϥϯλΠϜͷલํޓ׵ੑ 12
  5. όοΫσϓϩΠͷྲྀΕ # min-deploytarget͔Β࠷খϥϯλΠϜΛܾΊΔ swiftc main.swift -target x86_64-apple-macosx10.15 # OR #

    ࠷খϥϯλΠϜΛ௚઀ࢦఆ swiftc main.swift -runtime-compatibility-version 5.1 17
  6. υϥΠό͕΍Δ͜ͱ libswiftCompatibility51.aΛϦϯΫ swiftc -emit-object main.swift -o main.o ld main.o \

    -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility51.a \ -lswiftCore -o main 18
  7. ϦϯΫޙͷόΠφϦ $ du -h main_5_1_compat 56K main_5_1_compat $ objdump --macho

    --headers main_5_1_compat Sections: Idx Name Size VMA Type 0 __text 00000f9c 0000000100002d64 TEXT 1 __stubs 000000d8 0000000100003d00 TEXT 2 __stub_helper 000000f0 0000000100003dd8 TEXT 3 __swift5_entry 00000004 0000000100003ec8 DATA 4 __const 00000006 0000000100003ecc DATA 5 __cstring 0000009b 0000000100003ed2 DATA 6 __unwind_info 00000090 0000000100003f70 DATA 7 __got 00000008 0000000100004000 DATA 8 __const 00000008 0000000100004008 DATA 9 __objc_imageinfo 00000008 0000000100004010 DATA 10 __la_symbol_ptr 00000090 0000000100008000 DATA 11 __swift51_hooks 000000b8 0000000100008090 DATA 12 __data 00000009 0000000100008148 DATA 13 __bss 000000c8 0000000100008158 BSS $ du -h main 36K main $ objdump --macho --headers main Sections: Idx Name Size VMA Type 0 __text 0000000c 0000000100003fa4 TEXT 1 __swift5_entry 00000004 0000000100003fb0 DATA 2 __const 00000002 0000000100003fb4 DATA 3 __unwind_info 00000048 0000000100003fb8 DATA 4 __objc_imageinfo 00000008 0000000100004000 DATA 19
  8. ϥϯλΠϜؔ਺ͷ࣮ଶ #define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \ typedArgs, namedArgs)

    \ attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \ static Override_##name Override; \ static swift_once_t Predicate; \ swift_once( \ &Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \ if (Override != nullptr) \ return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \ swift_##name##Impl); \ return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \ } COMPATIBILITY_OVERRIDE(dynamicCastClass, const void *, , , swift::, (const void *object, const ClassMetadata *targetType), (object, targetType)) https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.h 22
  9. ϥϯλΠϜؔ਺ͷ࣮ଶʢϚΫϩల։ޙʣ const void * swift::swift_dynamicCastClass(const void *object, const ClassMetadata *targetType)

    { static Override_dynamicCastClass Override; static swift_once_t Predicate; swift_once(&Predicate, [](void *) { Override = getOverride_dynamicCastClass(); }, nullptr); if (Override != nullptr) return Override(object, targetType, swift_dynamicCastClassImpl); return swift_dynamicCastClassImpl(object, targetType); } https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.h 23
  10. ϑοΫηΫγϣϯ͔Β OverrideSection ߏ଄ମΛಡΈग़͢ // ϚΠφʔόʔδϣϯΞοϓ͝ͱʹมΘΔ #define COMPATIBILITY_OVERRIDE_SECTION_NAME __swift54_hooks static OverrideSection

    *getOverrideSectionPtr() { static OverrideSection *OverrideSectionPtr; static swift_once_t Predicate; swift_once(&Predicate, [](void *) { size_t Size; OverrideSectionPtr = static_cast<OverrideSection *>( lookupSection("__DATA", COMPATIBILITY_OVERRIDE_SECTION_NAME, &Size)); if (Size < sizeof(OverrideSection)) OverrideSectionPtr = nullptr; }, nullptr); return OverrideSectionPtr; } Override_dynamicCastClass swift::getOverride_dynamicCastClass() { auto *Section = getOverrideSectionPtr(); if (Section == nullptr) return nullptr; return Section->dynamicCastClass; } https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.cpp 24
  11. ϑοΫηΫγϣϯ in libswiftCompatibility51.a struct OverrideSection { uintptr_t version; #define OVERRIDE(name,

    ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ Override_ ## name name; #include "CompatibilityOverride.def" }; OverrideSection Swift51Overrides __attribute__((used, section("__DATA,__swift51_hooks"))) = { .version = 0, .conformsToSwiftProtocol = swift51override_conformsToSwiftProtocol, }; 25
  12. ෳ਺ͷݹ͍ϥϯλΠϜΛαϙʔτ͍ͨ͠ͱ͖ • ෳ਺ͷlibswiftCompatibilityX.aΛϦϯΫ͢Ε͹OK • ϥϯλΠϜ͸ࣗ਎ͷόʔδϣϯ޲͚ͷϑοΫηΫγϣϯ͔͠ ಡ·ͳ͍ͷͰׯব͠ͳ͍ swiftc main.swift -runtime-compatibility-version 5.0

    # υϥΠό͕ˣΛൃߦ ld main.o \ -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility50.a \ -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility51.a \ -lswiftCore -o main 26
  13. γϯϘϧॏෳ໰୊ ରԠࡁΈɻଟ෼ಈ͘ Back-deploy creation of global-actor-qualified function type metadata. #39280

    • ίϯύΠϥଆͱޓ׵ϥΠϒϥϦͷ࣮૷͕ऴΘͬͯΔ • ޓ׵ϥΠϒϥϦ libswiftCompatibilityConcurrency.a • طଘͷ࢓૊ΈͱͪΐͬͱࣅͯΔ 37
  14. // In "libswiftCore.dylib" in iOS 15 const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActor(...);

    // In "/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib" const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActorStandalone(...); // In "libswiftCompatibilityConcurrency.a" const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActorBackDeploy(...) { static BuilderFn builderFn; static dispatch_once_t builderToken; dispatch_once(&builderToken, ^{ // Prefer the function from the Swift runtime if it is available. builderFn = reinterpret_cast<BuilderFn>( dlsym(RTLD_DEFAULT, "swift_getFunctionTypeMetadataGlobalActor")); if (builderFn) return; builderFn = reinterpret_cast<BuilderFn>( dlsym(RTLD_DEFAULT, "swift_getFunctionTypeMetadataGlobalActorStandalone")); }); return builderFn(...); } https://github.com/apple/swift/blob/main/stdlib/public/BackDeployConcurrency/Metadata.cpp 38
  15. Concurrency back-deployؔ࿈ϦϯΫ • Make the back-deployed concurrency dylibs depend only

    on what's available in older runtimes • Make swift_async_extendedFramePointerFlags = 0 in back- deployed configurations • Back-deploy creation of global-actor-qualified function type metadata. • Use private concurrent queues for back-deployed 41