This is a follow up to the previous post on compling XNU 4570.41.2 for ARM64, but covering the newly released XNU 4903.221.2 (macOS 14.1). This guide is, again, mostly based on the kernelshamin guide.

The future of compilation for arm64 looked bad from Apple’s release of xnu-4570.71.2 which contained several broken components for the architecture. Thankfully, this release required only two minor modifications (and nothing to code!):

  1. We don’t have access to the device map database, nor the embedded_device_map tool, thankfully these are only needed to actually build for the device
  2. As before, Availability.h is needed but not included in the installhdrs stage - simply fixed by modifying EXTERNAL_HEADERS/Makefile

This release included Apple’s intended use for the MACHINE_CONFIG build variable. This allows the targetted AP to be specified as part of the build (or for multiple device builds to occur). In the original modifications, I hardcoded the T8011 board, but later included a great suggestion from @zhouwei (see issue #1) which did exactly what Apple has now released. An additional machine is also included, the BCM2837, the AP for the Raspberry Pi 3 - very cool! The big challenges that someone would need to resolve for the rpi3 is that a device map is needed, ideally they would create an embedded_device_map tool, and a custom iBoot to take over from the Pi’s bootloader and pass off to XNU. @zhouwei has done this for qemu and of course Corellium have done it better than anyone - it can be done!

tl;dr

The complication process is as simple as following the kernelshaman blog, with the following modifications:

  1. Use my repository for xnu 4903.221.2 - it contains modifications to the xnu source necessary for building
    • Note: if you would rather build from Apple’s source, check the diff from my repo for changes I made
  2. a copy of the TargetConditionals.h header must be made from the iPhoneOS SDK’s /usr/include directory to the iPhoneOS SDK’s /System/Library/Frameworks/Kernel.framework/Versions/A/Headers directory in order to build libfirehose
  3. When building: the SDK is “iphoneos”, the ARCH is “arm64”, and XNU’s build also needs ARCH_STRING_FOR_CURRENT_MACHINE_CONFIG=arm64

The Details

This process was tested on a mostly-clean macOS 10.14.2 with Xcode 10.1.

CTF Tools

The CTF tools (ctfconvert, ctfdump and ctfmerge) are executed as part of XNU’s build and are expected to be in your hosts’s SDK path.

For macOS 10.14.1 dtrace has had a version bump to 262.50.12. Compilation requires some additional header search paths to resolve locating elf.h and a few others.

tar zxvf dtrace-262.50.12.tar.gz
cd dtrace-262.50.12
mkdir obj sym dst
xcodebuild install -sdk macosx \
    -target ctfconvert -target ctfdump -target ctfmerge \
    ARCHS=x86_64 SRCROOT=$PWD OBJROOT=$PWD/obj \
    SYMROOT=$PWD/sym DSTROOT=$PWD/dst \
    HEADER_SEARCH_PATHS="$PWD/compat/opensolaris/** $PWD/lib/**"
sudo ditto \
    $PWD/dst/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain \
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
cd ..

AvailabilityVersions

AvailabilityVersions provides a perl script used as part of the XNU build. Build and installation is per the blog, except the install target is the iphoneos SDK.

AvailabilityVersions had a version bump to 33.200.4 in macOS 10.14.1, however the installation is as before.

tar zxvf AvailabilityVersions-33.200.4.tar.gz
cd AvailabilityVersions-33.200.4
mkdir dst
make install SRCROOT=$PWD DSTROOT=$PWD/dst
sudo ditto \
    $PWD/dst/usr/local/libexec \
    $(xcrun -sdk iphoneos -show-sdk-path)/usr/local/libexec
cd ..

libplatform Headers

Just three header files are required from this project. These are now at version 177.200.16, but install is the same.

tar zxvf libplatform-177.200.16.tar.gz
cd libplatform-177.200.16
sudo mkdir -p \
    $(xcrun -sdk iphoneos -show-sdk-path)/usr/local/include/os/internal
sudo ditto $PWD/private/os/internal \
    $(xcrun -sdk iphoneos -show-sdk-path)/usr/local/include/os/internal
cd ..

XNU Headers

The headers are ready to be built now. I’d recommend using my repo and check the diff to see what I did.

After the headers are installed, a copy of the TargetConditionals.h header must be made from the SDK’s /usr/include directory to the SDK’s /System/Library/Frameworks/Kernel.framework/Versions/A/Headers directory in order to build libfirehose.

git clone -b xnu-4903.221.2 https://github.com/fergofrog/xnu.git
cd xnu
make LOGCOLORS=y SDKROOT=iphoneos ARCH_CONFIGS=ARM64 MACHINE_CONFIGS=T8011 \
     KERNEL_CONFIGS=RELEASE ARCH_STRING_FOR_CURRENT_MACHINE_CONFIG=arm64 \
     installhdrs
sudo ditto $PWD/BUILD/dst $(xcrun -sdk iphoneos -show-sdk-path)
sudo cp $(xcrun -sdk iphoneos -show-sdk-path)/usr/include/TargetConditionals.h \
    $(xcrun -sdk iphoneos -show-sdk-path)/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/TargetConditionals.h
cd ..

libfirehose_kernel From libdispatch

The kernel libfirehose header and objects are required to build XNU. As before, the XNU headers and TargetConditionals.h need to be in place, however the new libdispatch 1008.220.2 requires several additional modifications, documented by the kernelsharman blog.

tar zxvf libdispatch-1008.220.2.tar.gz
cd libdispatch-1008.220.2
mkdir obj sym dst
awk '/include "<DEVELOPER/ {next;} /SDKROOT =/ {print "SDKROOT = macosx"; next;} {print $0}' \
    xcodeconfig/libdispatch.xcconfig > .__tmp__ && \
    mv -f .__tmp__ xcodeconfig/libdispatch.xcconfig
awk '/#include / { next; } { print $0 }' \xcodeconfig/libfirehose_kernel.xcconfig > .__tmp__ && \
    mv -f .__tmp__ xcodeconfig/libfirehose_kernel.xcconfig
xcodebuild install -sdk iphoneos -target libfirehose_kernel \
    SRCROOT=$PWD OBJROOT=$PWD/obj SYMROOT=$PWD/sym DSTROOT=$PWD/dst \
    ENABLE_BITCODE=no
sudo ditto $PWD/dst/usr/local \
    $(xcrun -sdk iphoneos -show-sdk-path)/usr/local
cd ..

XNU

Now it’s time to build XNU. With all the setup from before, this process is as simple as one command.

cd xnu
make LOGCOLORS=y SDKROOT=iphoneos ARCH_CONFIGS=ARM64 MACHINE_CONFIGS=T8011 \
     KERNEL_CONFIGS=RELEASE ARCH_STRING_FOR_CURRENT_MACHINE_CONFIG=arm64