Skip to content

0.21.0

Latest

Choose a tag to compare

@github-actions github-actions released this 29 Sep 08:04
fc27627

0.21.0

A minor release on top of 0.20.0. interface now prints the class members that a stripped OS framework no longer names β€” 53 of them across AppKit β€” lists class methods in vtable order, and marks Swift classes renamed for the Objective-C runtime with @objc(Name). ABI snapshots move to format version 6, so regenerate baselines saved by 0.20.0.

What's new

  • Class members named only by their method descriptor are recovered. In an image stripped of its local symbols (AppKit in the OS dyld shared cache), a public class method's implementation has no name left, and interface dropped it: NSTableViewDiffableDataSource and NSCollectionViewDiffableDataSource printed only init and deinit. These members are now read from the class's vtable, and diff, evolution and snapshots see them too.
  • Class members print in vtable order. interface lists a class's vtable methods first, in slot order β€” the source's declaration order, the way dump already walks them β€” then the remaining members by category as before. A slot nothing names is skipped. --sort-members-by-offset and the diff / evolution interfaces are unchanged.
  • @objc(Name) on renamed classes. A Swift class whose source gave the Objective-C runtime its own name (@objc(NSScrollPocket)) prints that attribute in interface, dump and the diff / evolution headers, or @_objcRuntimeName(Name) where the class uses Swift's native object model and @objc would not compile. macOS 27's AppKit has 74 such classes.

Fixes

  • A renamed class lost every recovered @objc and override on its members, and in a stripped image its Objective-C members printed as final. With an Objective-C superclass, its static field offsets could be a few bytes off.
  • init / init? was decided by the first closure in the signature: NSCollectionViewDiffableDataSource.init(collectionView:itemProvider:) printed as init? because its item provider returns an optional, and SwiftUI's failable CoreDisplayLink.init?(displayID:handler:) printed as init.
  • Reading an in-process image that is not in the dyld shared cache but was loaded above the shared region's start printed wrong member and IMP addresses. Fixed by MachOKitExtensions 0.1.2.

Breaking

  • The library no longer empties its per-image caches under memory pressure. A host that relied on that calls SharedCacheRegistry.shared.evictImagesWithoutLiveOwners() (@_spi(Internals) import MachOCaches) when it wants memory back; it evicts every image no live SwiftDeclarationIndexer still owns.
  • SharedCache (SPI Internals) is final and built by composition: final class Foo: SharedCache<Storage> { override func buildStorage(for:) … } becomes final class Foo { private let cache = SharedCache<Storage>(evictionGroup: …) }, looked up with cache.storage(in: machO) { build($0) }. init(), buildStorage(for:), buildStorage(), storage(), contains() and remove() are removed. SymbolIndexStore and InternedNodeReferenceCache are no longer its subclasses; their instance API is unchanged.

Compatibility

  • ABI snapshot formatVersion 5 β†’ 6. A snapshot saved by 0.20.0 is rejected with a format-version error rather than misreporting the recovered members as added; regenerate it with 0.21.0. The key scheme is unchanged.
  • Rendered output changes only where listed above: class member order in single-version interface, the recovered members, @objc(Name) and the renamed classes' members, and the init / init? corrections.
  • Dependency floors: MachOKitExtensions 0.1.2 (was 0.1.1), swift-capstone 6.0.1 ..< 7.0.0 (was 6.0.0; 6.0.1 restores the AArch64 backend for packages still spelling the pre-v6 trait). All other pins are unchanged from 0.20.0.
  • The command line is unchanged: no flag was added, removed or given a new default.

Requirements

  • Swift 6.2+
  • Xcode 26.0+

Full design: evolution proposals 0052–0054; implementation notes DescriptorOnlyVTableMembers.md, CustomObjCClassNames.md and Modules/MachOCaches.md.