Apple Internals: Swift in the Kernel

Apple Internals: Swift in the Kernel

Apple Internals: Swift in the Kernel A new series reverse-engineering Apple’s internals. Josh Maine | Jun 18, 2026


After WWDC, I saw Devon Maloney posted a slide saying Apple has “started writing parts of the core operating system kernel in Swift” for the 27 releases. First steps toward a memory-safe kernel. What does this even mean?!

在 WWDC 之后,我看到 Devon Maloney 发布了一张幻灯片,称苹果已在 27 系列版本中“开始使用 Swift 编写核心操作系统内核的部分代码”。这是迈向内存安全内核的第一步。这到底意味着什么?!

Naturally I dropped what I was doing and went grepping through the iOS 27 kernelcache. Alas, nothing came of it. All is not lost though: I found the Embedded Swift runtime in macOS 27, sitting in com.apple.kec.pthread of all places. Then I went poking around the root filesystem and it turns out Apple gave the whole effort a name: KernelKit.

我自然放下了手头的工作,开始在 iOS 27 的 kernelcache 中进行搜索。遗憾的是,一无所获。不过,情况并非完全没有进展:我在 macOS 27 中发现了 Embedded Swift 运行时,它竟然位于 com.apple.kec.pthread 中。随后,我在根文件系统中进行了一番探究,结果发现苹果为整个项目起了一个名字:KernelKit。

Let’s dissect it. Where this is going: the C/C++ core (Mach, BSD, IOKit) is untouched. Swift shows up only as a small Embedded runtime inside specific KernelKit kexts at the extension layer.

让我们来剖析一下。目前的进展是:C/C++ 核心(Mach、BSD、IOKit)保持不变。Swift 仅作为一种小型嵌入式运行时,出现在扩展层特定的 KernelKit 内核扩展(kext)中。

A new directory in /System

/System 下的新目录

On the macOS 27 root volume (26A5353q), right next to /System/DriverKit, are two kexts: 在 macOS 27 的根卷(26A5353q)上,紧邻 /System/DriverKit 的是两个内核扩展:

/System/KernelKit/
 └── System/Library/Extensions/
  ├── Libm.kext/
  │   ├── Libm
  │   ├── Libm_kasan
  │   └── Info.plist
  └── pthread.kext/
      ├── pthread
      ├── pthread_development
      ├── pthread_kasan
      └── Info.plist

The Info.plist for the pthread one is where it gets fun: pthread 的 Info.plist 文件里藏着有趣的内容:

"CFBundleSupportedPlatforms" => ["KernelKit.MacOSX"]
"DTPlatformName" => "kernelkit.macosx"
"DTSDKName" => "kernelkit.macosx27.0.internal"
"DTXcode" => "2700"

And version.plist: 以及 version.plist:

"ProjectName" => "libpthread_kernelkit"
"BuildAliasOf" => "libpthread"

So there’s an internal SDK called kernelkit.macosx27.0.internal, and libpthread_kernelkit is a separate Xcode target building from the same libpthread sources as the regular kext. Libm gets the same treatment: ProjectName: Libm_kernelkit.

因此,存在一个名为 kernelkit.macosx27.0.internal 的内部 SDK,而 libpthread_kernelkit 是一个独立的 Xcode 构建目标,它与常规内核扩展使用相同的 libpthread 源码。Libm 也采用了同样的做法:项目名称为 Libm_kernelkit。

If this is giving you DriverKit déjà vu, you are on to something: its own directory under /System, its own SDK, its own Mach-O platform constant, the same playbook seven years later.

如果这让你有种 DriverKit 的既视感,那你的直觉很准:在 /System 下有独立的目录、独立的 SDK、独立的 Mach-O 平台常量,七年后,苹果又用了同样的套路。

New Mach-O platform IDs

新的 Mach-O 平台 ID

The LC_BUILD_VERSION for these binaries says: 这些二进制文件的 LC_BUILD_VERSION 显示:

cmd LC_BUILD_VERSION
platform 25
minos 27.0
sdk 27.0

The Mach-O platform enum currently goes up to 24 (visionOSExclaveKit). Nothing in public headers, LLVM, or loader.h knows what 25 is yet; ipsw just printed Platform(25) until I went and added the constants.

目前的 Mach-O 平台枚举最高只到 24 (visionOSExclaveKit)。公共头文件、LLVM 或 loader.h 中还没有人知道 25 是什么;在我手动添加常量之前,ipsw 工具只会打印出 Platform(25)。

Then I checked the iOS 27 kernelcache’s pthread kext, expecting the boring old absence of LC_BUILD_VERSION that iOS 26 had: 接着我检查了 iOS 27 kernelcache 中的 pthread 内核扩展,本以为会像 iOS 26 那样平淡无奇地缺失 LC_BUILD_VERSION

LC_BUILD_VERSION
Platform: Platform(26), MinOS: 27, SDK: 27

That’s notable for two reasons. LC_BUILD_VERSION is the stamp a Mach-O carries to record which OS it was built for, and Apple tracks each one by a number rather than a name. Last year’s iOS 26 build of this kext had no such stamp at all, so its mere presence here is new. And the number is 26, not the 25 macOS reported a moment ago. Apple could have filed every OS’s kernel-Swift code under one shared platform, but instead each OS gets its own: macOS is 25, iOS is 26, with the rest in the table below.

这一点值得注意,原因有二。LC_BUILD_VERSION 是 Mach-O 文件携带的标记,用于记录它是为哪个操作系统构建的,苹果通过数字而非名称来追踪每一个平台。去年 iOS 26 构建的该内核扩展完全没有这个标记,所以它的出现本身就是个新事物。而且这个数字是 26,而不是刚才 macOS 报告的 25。苹果本可以将所有操作系统的内核 Swift 代码归入一个共享平台,但他们却为每个操作系统分配了独立的 ID:macOS 是 25,iOS 是 26,其余的见下表。

To get the actual names I pulled the table out of the Xcode 27 beta linker. ld keeps a static array of 96-byte platform descriptors (from Platform.cpp); the uint32 ID sits at offset +0x20 in each. Calibrated against the known entries 23/24 (visionOS-exclaveCore/Kit), the six new ones are:

为了获取确切名称,我从 Xcode 27 测试版的链接器中提取了该表。ld 维护着一个 96 字节平台描述符的静态数组(来自 Platform.cpp);uint32 ID 位于每个描述符的 +0x20 偏移处。根据已知的 23/24 条目(visionOS-exclaveCore/Kit)进行校准,这六个新条目如下:

IDname (from ld @ 0x1001c67c8+)
25macOS-kernelKit
26iOS-kernelKit
27tvOS-kernelKit
28watchOS-kernelKit
29visionOS-kernelKit (alias xrOS-kernelKit)
30bridgeOS-kernelKit

The table ends at 30. All six are new in the 27 train; iOS 26.6’s pthread kext (libpthread-539) has no LC_BUILD_VERSION at all. 25 and 26 are the only ones I’ve seen in shipping binaries so far.

该表在 30 处结束。这六个条目在 27 系列版本中都是全新的;iOS 26.6 的 pthread 内核扩展(libpthread-539)完全没有 LC_BUILD_VERSION。到目前为止,我在正式发布的二进制文件中只见过 25 和 26。

The Xcode beta toolchain already knows

Xcode 测试版工具链已经知晓

TargetConditionals.h has no TARGET_OS_KERNELKIT, and there’s no KernelKit.platform under Contents/Developer/Platforms/. But cstrings from the toolchain binaries provide some more clues:

TargetConditionals.h 中没有 TARGET_OS_KERNELKITContents/Developer/Platforms/ 下也没有 KernelKit.platform。但工具链二进制文件中的 C 字符串提供了一些线索:

ld:macOS-kernelKit iOS-kernelKit tvOS-kernelKit watchOS-kernelKit visionOS-kernelKit bridgeOS-kernelKit
/System/KernelKit/usr/lib
/System/KernelKit/usr/lib/swift
/System/KernelKit/System/Library/Frameworks
kernelKit can only be used with -r, -kext and -static
tapi and swift-frontend:
TARGET_OS_KERNELKIT environment
kernelkit kernelkit_osx kernelkit_ios kernelkit_tvos kernelkit_watchos kernelkit_bridgeos kernelkit_xros

Six per-OS variants. bridgeOS gets one, because apparently the Touch Bar needs in-kernel Swift before iOS does. There’s a TARGET_OS_KERNELKIT preprocessor conditional. The linker hard-codes /System/KernelKit/usr/lib/swift as a search path, which tells you where the in-kernel Swift stdlib is going to live once it grows past what’s statically baked into pthread today. And the ld error string kernelKit can only be used with -r, -kext and -static confirms there’s no dylib or executable output, just kext bundles and object files.

每个操作系统对应一个变体。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 包和目标文件。

The linker, the TBD stub tool, and the Swift compiler can all already target this thing. Apple just hasn’t published the headers or the SDK yet.

链接器、TBD 存根工具和 Swift 编译器都已经可以针对此目标进行工作。只是苹果尚未发布相关的头文件或 SDK。

The Swift bit

Swift 的部分

The /System/KernelKit/ pthread binary is the one that ends up in the kernelcache. I know because the UUIDs match:

/System/KernelKit/ 下的 pthread 二进制文件最终会被放入 kernelcache 中。我知道这一点是因为它们的 UUID 匹配:

binaryUUIDplatformswift syms
/S/KernelKit/.../pthread (arm64e)F44A1FAB-1F9C-3E38-9C8B-1B238A61939C2537
KC fileset com.apple.kec.pthreadF44A1FAB-1F9C-3E38-9C8B-1B238A61939C2537
/S/L/E/pthread.kext (arm64e)25FC1559-E358-33B4-8B84-5627969BC4B01 (macOS)0
KDK pthread.kext (arm64e)25FC1559-E358-33B4-8B84-5627969BC4B01 (macOS)0

Same libpthread-553 source, two builds. The “normal” macOS-platform build, the one shipped in /System/Library/Extensions and the KDK, has no Swift. The KernelKit-platform build lives in /System/KernelKit, gets prelinked into the kernelcache, and carries the Embedded Swift runtime statically linked in.

同样的 libpthread-553 源码,两种构建版本。在 /System/Library/Extensions 和 KDK 中发布的“常规” macOS 平台构建版本不包含 Swift。而 KernelKit 平台构建版本位于 /System/KernelKit 中,会被预链接到 kernelcache 中,并静态链接了 Embedded Swift 运行时。

Here’s what’s actually in there: 以下是其中的实际内容:

fffffe0008ab79e4 T _swift_allocE