Darwin Kernel Compile

Jan 13, 2006

Compiling the Darwin Kernel

I’m writing this how-to beause when I wanted to enable MAC address spoofing on my Powerbook, it was a little bit more of an adventure than I had hoped for. I had to look through a number of different tutorials, picking and choosing what I knew from my experience with Mac OSX and Linux/BSD to be correct; there are a number of conflicting directions in other tutorials. Hopefully mine makes sense the whole way through.

Prepare the Build Environment

To build a Mach kernel you need a number of things, namely, XCode, bootstrap_cmds, Libstreams, cctools, kext-tools, IOKitUser and xnu. The former is included on any new Mac (run the “Developer Tools” installer in the Applications folder) and the latter must be obtained from the Apple developers site, which requires a (free) membership login.

  1. Assuming you have XCode installed, the first thing to do is grab the packages that you’ll need for building the kernel. They can be obtained from the abovementioned location, http://www.opensource.apple.com/darwinsource/tarballs/apsl. You’ll need the following packages:

  2. Untar all of those packages:

    # cd /usr/local/src; for i in $(ls); do tar zxvf $i; done
    Whew, that was tough. Go make a sandwich before continuing.

  3. Let’s build what we need in bootstrap_cmds and Libstreams, because they’re easy.
    Note: I’m performing all of these commands as root, which isn’t enabled be default on Mac OS X (I think). Most people will probably more comfortable with untarring/building all of these things in their own userspace (say, your home directory) and then using sudo when you need to be root. I come from Linux, where Real Men use su.
    # cd bootstrap_cmds-*/relpath.tproj
    # make
    # make install
    Now, Libstreams:
    # cd ../../Libstreams-*
    # make
    # make install

  4. Time to build cctools, it’s a little bit more involved.
    # cd ../cctools-*
    # cp /usr/include/sys/unistd.h /System/Library/Frameworks/Kernel.framework/Headers/sys/ We only care about some of what cctools has to offer, so bust open it’s Makefile and lets edit it a little. We’re going to comment out the two lines (28 and 29) that define COMMON_SUBDIRS and redefine it asCOMMON_SUBDIRS = libstuff libmacho misc.
    #COMMON_SUBDIRS = libstuff as gprof misc libmacho ld libdyld \
    # mkshlib otool profileServer RelNotes man cbtlibs
    COMMON_SUBDIRS = libstuff libmacho misc That’s what it should look like when you’re done, at which point you’re ready to build and install it.
    # make RC_OS=macos
    # cp misc/seg_hack.NEW /usr/local/bin/seg_hack
    # cd ld
    # make RC_OS=macos kld_build
    # cp static_kld/libkld.a /usr/local/lib
    # ranlib /usr/local/lib/libkld.a

  5. Compiling kextsymboltool is where I ran into trouble, well, because I grabbed the wrong IOKit version (I didn’t have the newest one), so watch out for that. If you get the right version, everything should go smoothly.
    # cd ../../
    # mv IOKitUser* IOKit
    # mv IOKit /usr/include
    # mv /usr/include/IOKit/kext.subproj /usr/include/IOKit/kext
    # cp -fpr cctools*/include/mach-o /usr/include
    # cp -fpr cctools*/include/mach/* /usr/include/mach
    # cd kext_tools*
    # gcc kextsymboltool.c -o kextsymboltool
    # cp kextsymboltool /usr/local/bin
    # chmod 755 /usr/local/bin/kextsymboltool

Done! Well, sort of. The build environment is all set up, so now if you ever want to build a new kernel, you can start on the next step.

Building the Kernel

  1. The first thing to do is apply any patches that you desire. You’ll probably be adding some patches; otherwise, why would you be rebuilding the kernel? I’m using a patch to enable setting the MAC address of my network cards manually (for MAC address spoofing), one that boots my mac in verbose mode by default and a third that allows all users (not just root) to craft and send raw packets. They are available from the following locations (the direct links are for xnu version 517):

    • BIOCSHDRCMPLT - MAC address patch by Jeff Nathan
    • FORCE_VERBOSE - Verbose booting patch by Peter Bartoli
    • RAW4ALL - Raw packet creation patch also by Peter Bartoli
      To begin with, let’s move to the kernel source directory:
      # cd ../xnu*
      Grab the three patches:
      # wget http://cerberus.sourcefire.com/%7Ejeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
      # wget http://slagheap.net/etherspoof/517/FORCE_VERBOSE.patch
      # wget http://slagheap.net/etherspoof/517/RAW4ALL.patch
      and patch the kernel source:
      # patch -p0 -b --verbose --suffix=.orig < RAW4ALL.patch
      # patch -p0 -b --verbose --suffix=.orig < FORCE_VERBOSE.patch
      # patch -p0 -b --verbose --suffix=.orig < BIOCHSHDRCMPLT-10.3.3.patch Pay attention to the output of those patches; if the source changes significantly from the time I wrote this page, they might not apply properly. If they work fine, you can move on.
  2. Finally, we will actually build the kernel:
    # make exporthdrs
    # make
    The new kernel is now in BUILD/obj/RELEASE_PPC/mach_kernel under the current directory. Next, we’ll install and prepare to boot with the new kernel.

  3. To install, just copy the new kernel to the root (/) directory. We’ll name it differently from the stock kernel, so that you have something to fall back on if your new kernel fails to boot properly.
    # cp BUILD/obj/RELEASE_PPC/mach_kernel /mach_kernel.new
    # chmod 644 /mach_kernel.new
    # chown root.wheel /mach_kernel.new
    Now configure the machine to boot from the new kernel:

# nvram boot-file=\nvram boot-device | awk -F , ’{print $1}’ | awk ’{print $2}’`,mach_kernel.new`

Note: That is supposed to work, but really, didn’t for me. I had to make a leap-of-faith and replace the stock kernel with the one that I just built.
# cp mach_kernel mach_kernel.bak
# cp mach_kernel.new mach_kernel
# nvram boot-file=""
and then reboot.

You should be all set! Upon reboot, the computer should boot with your new kernel. In the event something goes wrong, you can zap the PRAM by holding option-apple-p-r through three startup chimes. Alternatively, hold option-apple-o-f which will boot into OpenFirmware; type “reset-all” and then “mac-boot”. If neither of those fixes the problem, hold option-apple-n-v during boot to reset the NVRAM.