Apple 内部:内核中的 Swift

Lobsters Hottest 新闻

摘要

Apple 已开始通过一项名为 KernelKit 的新工作将 Swift 集成到内核中,嵌入式 Swift 运行时出现在 macOS 和 iOS 中,标志着向内存安全内核扩展迈出了一步。

<p><a href="https://lobste.rs/s/5j33bp/apple_internals_swift_kernel">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/22 01:29

# Apple 内部解析:内核中的 Swift 来源:https://blog.calif.io/p/apple-internals-swift-in-the-kernel WWDC 之后,我看到 Devon Maloney 发布了一张幻灯片(https://x.com/plailect/status/2064138356259213475),称 Apple 已在 27 版本中“开始用 Swift 编写核心操作系统内核的部分内容”。迈出迈向内存安全内核的第一步。这到底意味着什么?! 我自然放下手头工作,开始在 iOS 27 的内核缓存中搜索。可惜一无所获。不过并非全无收获:我在 macOS 27 的 `com.apple.kec.pthread` 中找到了 Embedded Swift 运行时——居然藏在这个地方。然后我翻查了根文件系统,发现 Apple 给整个努力起了个名字:**KernelKit**。 我们来剖析一下。 XNU 示意图,显示 C/C++ 核心(Mach、BSD、IOKit)保持不变,新的 KernelKit 内核扩展以及 Embedded Swift 运行时添加在内核扩展层边缘(https://substackcdn.com/image/fetch/$s_!9HB8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bb311ae-2b1f-4900-b2b6-06a14ecd95cc_840x660.png) *发展方向:C/C++ 核心(Mach、BSD、IOKit)未被触及。Swift 仅以小型 Embedded 运行时形式出现在扩展层的特定 KernelKit kext 中。* 在 macOS 27 根卷(`26A5353q`)上,紧挨着 `/System/DriverKit` 的是两个 kext: 其中 pthread kext 的 `Info.plist` 有趣的部分如下: 以及 `version.plist`: 所以有一个名为 `kernelkit.macosx27.0.internal` 的内部 SDK,而 `libpthread_kernelkit` 是一个独立的 Xcode 目标,与普通 kext 使用相同的 libpthread 源码构建。`Libm` 也采用了相同处理:`ProjectName: Libm_kernelkit`。 如果这让你想起 DriverKit(https://developer.apple.com/documentation/driverkit),那你的感觉没错:它有自己的 `/System` 目录、自己的 SDK、自己的 Mach-O 平台常量——七年后的同一套打法。 这些二进制文件的 `LC_BUILD_VERSION` 显示: 当前 Mach-O 平台枚举值最高到 24(`visionOSExclaveKit`)。公共头文件、LLVM 或 `loader.h` 都不知道 25 是什么;`ipsw` 只会打印 `Platform(25)`,直到我手动添加了常量。 然后我检查了 iOS 27 内核缓存中的 pthread kext,本以为会和 iOS 26 一样老套地缺失 `LC_BUILD_VERSION`: 但这值得注意,原因有二。`LC_BUILD_VERSION` 是 Mach-O 携带的印记,记录它为哪个操作系统构建,Apple 用数字而非名称来追踪每个系统。去年 iOS 26 构建的这个 kext 根本没有这种印记,所以它出现在这里本身就是新现象。而且数字是 **26**,而不是刚才 macOS 报告的 **25**。Apple 本可以将所有操作系统的内核 Swift 代码归入同一个共享平台,但实际是每个操作系统都有自己的:macOS 是 25,iOS 是 26,其余的见下表。 为了获取实际名称,我提取了 Xcode 27 beta 链接器中的表格。`ld` 维护着一个 96 字节平台描述符的静态数组(来自 `Platform.cpp`);`uint32` ID 位于每个描述符偏移 `+0x20` 处。通过与已知条目 23/24(`visionOS-exclaveCore`/`Kit`)校准,六个新条目如下: 表格结束于 30。这六个都是 27 版本中新增的;iOS 26.6 的 pthread kext(libpthread-539)根本没有 `LC_BUILD_VERSION`。到目前为止,我只在发布的二进制文件中看到过 25 和 26。 `TargetConditionals.h` 中没有 `TARGET_OS_KERNELKIT`,`Contents/Developer/Platforms/` 下也没有 `KernelKit.platform`。但工具链二进制文件中的一些 cstrings 提供了更多线索: - `ld`: - `tapi` 和 `swift-frontend`: 六个按操作系统区分的变体。bridgeOS 也有一个,因为显然 Touch Bar 需要比 iOS 更早拥有内核级 Swift。存在 `TARGET_OS_KERNELKIT` 预处理条件。链接器硬编码了 `/System/KernelKit/usr/lib/swift` 作为搜索路径,这暗示了内核级 Swift 标准库在超出当前 pthread 中静态嵌入部分之后将要存放的位置。而 ld 错误字符串 `kernelKit can only be used with -r, -kext and -static` 确认了没有 dylib 或可执行输出,只有 kext 捆绑包和目标文件。 链接器、TBD 存根工具和 Swift 编译器都已经可以针对这个东西进行编译。Apple 只是还没有发布头文件或 SDK。 `/System/KernelKit/` 中的 pthread 二进制文件最终会进入内核缓存。我之所以知道,是因为 UUID 匹配: 相同的 libpthread-553 源码,两个构建。普通的 macOS 平台构建(即部署在 `/System/Library/Extensions` 和 KDK 中的那个)没有 Swift。KernelKit 平台构建位于 `/System/KernelKit`,被预链接到内核缓存中,并静态链接了 Embedded Swift 运行时。 实际内容如下: `_swift_embedded_*` 系列与开放 Swift 仓库中的 `stdlib/public/core/EmbeddedRuntime.swift`(https://github.com/swiftlang/swift/blob/main/stdlib/public/core/EmbeddedRuntime.swift)匹配。`$e` 符号混淆前缀是文档记录(https://github.com/swiftlang/swift/blob/main/docs/ABI/Mangling.rst)的嵌入式 Swift 前缀(常规 Swift 使用 `$s`;此切换在 #77923(https://github.com/swiftlang/swift/pull/77923)中启用),而 `_$es16_emptyBoxStorageSi_Sitvp` 反混淆后为 `Swift._emptyBoxStorage : (Swift.Int, Swift.Int)`。 没有 `__swift5_*` 反射段,这对于嵌入式 Swift 是正确的;泛型被单态化,且没有运行时元数据。整个运行时大约 2.4 KB 的 `__TEXT_EXEC.__text`。 我在 IDA 中打开了它,以确保这不是 37 个 `ret` 指令伪装成的运行时。`swift_release` 是一个真正的原子引用计数递减,带有 `brk #1` 下溢陷阱和当计数归零时对 `_swift_embedded_invoke_heap_object_destroy` 的调用。`swift_once` 是一个带有自旋等待的 CAS 一次性操作。`swift_dynamicCast` 是 500 字节的元数据链遍历和存在类型处理。`_emptyBoxStorage` 处的数据是 `(0, 0xFFFFFFFFFFFFFFFF)`,即不朽的空盒单例,这证实了这是真正的运行时,而非 37 个伪装起来的存根。 `com.apple.kec.Libm` 在 macOS 内核缓存中已经存在一段时间了(在 26.6 中就有,源码版本 3312)。新的是它使用 KernelKit SDK 重新构建(`Libm_kernelkit`,平台 25,源码版本 3326)并移到了 `/System/KernelKit`。它包含 65 个数学符号:`_cbrt`、`__sincos_stret`、`__ceilf16`、float16 内建函数等等。没有自己的 Swift 符号;它只是被纳入 KernelKit 家族,推测是为了让 Swift 的 `Double`/`Float` 操作有东西可链接。 我在 IDA 中检查了公共 Swift 入口点的交叉引用:`swift_retain`、`swift_release`、`swift_once`、`swift_dynamicCast`、`swift_allocEmptyBox`。唯一的内部调用者是 `swift_dynamicCast` 调用 `swift_release` 来清理自身。十年历史的 pthread C 代码(`_psynch_mutexwait`、`_bsdthread_create`)从未触及 Swift。 然后我扫描了所有 370 个 macOS 内核缓存文件集条目,查找其他任何地方的 `swift_*` 引用,即是否有其他 kext 链接了这个运行时: 只有一条命中——定义了它们的那个 kext:37 个符号中有 23 个是全局导出符号,而内核缓存中没有其他任何组件导入它们。该运行时已被链接、在启动时加载,但处于空闲状态。 iOS 27 则倒退了一步:pthread 和 Libm 是 KernelKit 平台的二进制文件(平台 26),但 Swift 运行时根本没有被链接进来,相同的 libpthread-553 源码,只是使用了不同的构建配置。 目前,Swift 内核运行时仅存在于 macOS 上且未被引用。这在我看来,部署顺序是:先发布 SDK 和运行时,观察一个或两个测试周期没有破坏任何东西,然后开始部署实际的、会链接 `_swift_retain` 等函数的 Swift 内核组件。iOS 现在先有了平台框架,运行时稍后才会加入。 XNU 本身仍然完全是 C/C++。KDK 的 `kernel.release.t6050.dSYM`(`t6050` 是 M5 Pro SoC)有 2,106 个 DWARF 编译单元,`DW_AT_language` 的分布为:1,855 个 `DW_LANG_C11`、249 个 `DW_LANG_C_plus_plus_14`、2 个 `DW_LANG_Mips_Assembler`,以及零个 `DW_LANG_Swift`。在 t6041(M4 Max)和 KASAN 构建上也是如此。编译器每个源文件发出一个编译单元,所以这不可能隐藏在被剥离的符号后面。无论 Swift 如何到来,它都是作为 KernelKit 组件到来,而不是对 Mach 的重写。 另外,如果有 Apple 员工想泄露 `KernelKit.macosx.sdk`,我会以应有的尊重对待它。 附注:忠实的读者们,是的,我们很快就会发布关于 Swift 和 exclaves 的博客。请耐心等待。 #### 关于此帖的讨论 ### 想要更多?

相似文章

将Swift引入Apple II

Lobsters Hottest

一位开发者创建了SwiftII,这是一个为Apple II打造的Swift风格迷你开发环境,包含REPL、文件浏览器和文本编辑器,为复古硬件带来了现代编程体验。

Swift Package Index 加入 Apple

Hacker News Top

Swift Package Index 是一个由社区维护的 Swift 包目录,现正式加入 Apple,这对 Swift 开发者生态系统来说意义重大。

苹果发布全新 Apple Silicon 端侧推理引擎

Reddit r/LocalLLaMA

苹果在 WWDC 上发布了 CoreAI,这是一款适用于 Apple Silicon 的全新端侧推理引擎,将取代 CoreML,并通过优化推理支持多达 200 亿参数的更大模型,重点面向手机和平板设备。

Apple Core AI Framework

Hacker News Top

Apple 推出 Core AI Framework,一种用于设备端机器学习的新工具。