watchthelight labs

Link checks and ABI buckets for macOS 11 to 15 #7

openmacos-abi
watchthelight 2026-10-21

The kext is meant to build once (minimum macOS 11) and link everywhere; the Metal accelerator and plugin need one build per ABI bucket. Kernel collections and dyld caches for 20G1443, 21H1320, 22H730, 23J631 and 24H32 are being extracted; next: kcabi linkcheck of XeGfx against each, and kcabi gfxdump.py + compare.py to find where IOAcceleratorFamily2 / IOGraphics / IOSurface changed.

watchthelight 2026-10-21

First pass done (2026-10-21). Kernel collections and dyld caches for 20G1443 (11.7.11), 21H1320 (12.7.6), 22H730 (13.7.8), 23J631 (14.8.9) and 24H32 (15.8.1) were extracted from Apple's own installers; 25G241 (26.7.1) is the test machine.

XeGfx kernel side: the kext (one binary) links against all six kernels, and tools/link.sh now checks every collection it finds. The older kernels export four names Tahoe does not (allproc, proc0, kmem_alloc_contig, vm_page_replace); the shim defined them too, the same trap as #1, so they are renamed now.

Graphics families (kcabi gfxdump.py, baselines in abi/graphics/<build>), compared by symbol name per vtable slot:

Step Changed vtables Notes
11 to 12 84 every IOService subclass changes from slot 4 (9 removed, 1 added): base class churn, inference
12 to 13 84 same pattern, 1 removed
13 to 14 4 IOAccelMTLEvent2, IOSurfaceDeviceMemoryRegion, IOSurfaceMemoryRegion, IOSurfaceSharedEvent (one slot added)
14 to 15 0
15 to 26 0

So the accelerator side looks like four buckets: 11, 12, 13, and 14 to 26. Caveats: unnamed (stripped) slots are not compared, instance sizes could not be read for these families (kcabi's MetaClass heuristic returns "?"), and Tahoe's change in which methods are exported is not visible in a layout comparison. Userspace (MTLIOAccel* classes in the dyld caches) is next.

Reply on GitHub