Skip to content

Instantly share code, notes, and snippets.

@Superbil
Last active July 8, 2022 10:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Superbil/7508a6d25f13dbadda48962aceb28e25 to your computer and use it in GitHub Desktop.
Save Superbil/7508a6d25f13dbadda48962aceb28e25 to your computer and use it in GitHub Desktop.
Kernel Debug Kit 11.0 build 20A5374i
Kernel Debug Kit for macOS - Read Me
Use the Kernel Debug Kit (KDK) to debug kernel-level code, such as kernel extensions you create.
Performing Two-Machine Debugging
The KDK supports the debugging of kernel-level code, such as kernel extensions, from a second Mac.
- The target device is the Mac that runs the code you want to debug.
- The host device is the Mac that runs the debugger.
Identify the Device Compatibility
On Apple silicon, perform two-machine debugging using your Mac’s built-in Ethernet ports.
On Intel-based Mac computers, perform two-machine debugging using your Mac’s built-in Ethernet ports, the Ethernet port on the Apple Thunderbolt display, or the Apple Thunderbolt to Gigabit Ethernet adapter. You may also use third-party Thunderbolt Ethernet adapters that support one of the following chipsets:
• Broadcom C-IV
• Aquantia AQC107/113
• Intel 82574L
Note: You cannot perform two-machine debugging using USB Ethernet adapters or wireless networking on any Mac.
You must connect the host and target device to the same network, but there are no other restrictions on how the devices connect to that network.
Configure an Apple Silicon Mac as a Target Device
Use the following steps to configure your Apple silicon Mac as a target device for debugging.
Step 1: Modify the Security Configuration of Your Mac
Modify the security configuration of your system as follows:
1. Reboot your system in Recovery Mode.
2. Set the Boot Policy to “Reduced Security”.
⁃ If you are debugging a kernel extension, you will also need to enable kernel extensions from identified developers.
3. Launch Terminal and run the following command to disable System Integrity Protection (SIP):
⁃ csrutil disable
4. Reboot your Mac computer.
Step 2: Identify the Correct Ethernet Device
Run the ifconfig tool in Terminal to identify which Ethernet device your target device uses to connect to the network. In the following example, en1 is the Ethernet device connected to the network.
en0: flags=8963 mtu 1500
 options=60
 ether 32:00:13:er:19:e0
 media: autoselect 
 status: inactive
en1: flags=8863 mtu 1500
 options=10b
 ether 40:6c:8f:5b:a2:96
   inet6 fe80::426c:8fff:fe5b:a296%en2 prefixlen 64 scopeid 0x4
   inet6 2620::1b07:114:426c:8fff:fe5b:a296 prefixlen 64 autoconf
   inet6 2620::1b07:114:88d6:bbba:7ac9:b0a7 prefixlen 64 autoconf temporary
   inet 10.128.19.135 netmask 0xfffff800 broadcast 10.128.23.255
   nd6 options=1
   media: autoselect (1000baseT )
   status: active
Step 3: Set the boot-args
Run the nvram tool in Terminal to update your target device’s boot args. Include the following keys:
• debug=0x44—Tells the kernel to wait for a debugger to attach to the device, when the kernel receives a non-maskable interrupt (NMI).
• kdp_match_name=enX—Set the value of this key to the Ethernet device (en0, en1, etc.) identified in Step 2: Identify the Correct Ethernet Device.
• wdt=-1—Disables watchdog monitoring.
For example:
sudo nvram boot-args=“debug=0x44 kdp_match_name=en1 wdt=-1”
Step 4: Reboot the Device
Upon reboot, you may connect to your target device from the host.
Configure an Intel-Based Mac as a Target Device
Use the following steps to configure your target device for debugging.
Step 1: Modify the Security Configuration of Your Mac
Modify the security configuration of your system as follows:
1. Reboot your system in Recovery Mode.
2. If your device has the Apple T2 Security Chip, set the Secure Boot policy to “Medium Security”.
3. Launch Terminal and run the following command to disable System Integrity Protection (SIP):
⁃ csrutil disable
4. Reboot your Mac computer.
Step 2: Identify the Correct Ethernet Device
Run the ifconfig tool in Terminal to identify which Ethernet device your target device uses to connect to the network. In the following example, en1 is the Ethernet device connected to the network.
en0: flags=8963 mtu 1500
 options=60
 ether 32:00:13:er:19:e0
 media: autoselect 
 status: inactive
en1: flags=8863 mtu 1500
 options=10b
 ether 40:6c:8f:5b:a2:96
   inet6 fe80::426c:8fff:fe5b:a296%en2 prefixlen 64 scopeid 0x4
   inet6 2620::1b07:114:426c:8fff:fe5b:a296 prefixlen 64 autoconf
   inet6 2620::1b07:114:88d6:bbba:7ac9:b0a7 prefixlen 64 autoconf temporary
   inet 10.128.19.135 netmask 0xfffff800 broadcast 10.128.23.255
   nd6 options=1
   media: autoselect (1000baseT )
   status: active
Step 3: Set the boot-args
Run the nvram tool in Terminal to update your target device’s boot args. Include the following keys:
• debug=0x44—Tells the kernel to wait for a debugger to attach to the device, when the kernel receives a non-maskable interrupt (NMI).
• kdp_match_name=enX—Set the value of this key to the Ethernet device (en0, en1, etc.) identified in Step 2: Identify the Correct Ethernet Device.
• wdt=-1—Disables watchdog monitoring.
For example:
sudo nvram boot-args=“debug=0x44 kdp_match_name=en1 wdt=-1”
Step 4: Reboot the Device
Upon reboot, you may connect to your target device from the host.
Configure the Host Device
Configure your host device to initiate debugging using the following steps:
Step 1: Install Xcode 12 or later
Install Xcode, including the command-line tools, on the host device.
Step 2: Install the KDK
Install this KDK on the host device.
Trigger the Target Device to Wait for the Debugger
After you configure the target device, it halts and waits for an external debugger to attach in the following situations:
• If the target device panics, it automatically halts and waits for an external debugger to attach.
• If you trigger an NMI on the target device, the device halts and waits for an external debugger to attach.
Connect the Debugger to the Target Device
Run lldb from Terminal and use the kdp-remote command to connect to the target device. That command accepts the hostname or IP address of the target device, and creates a debugger connection to it.
(lldb)kdp-remote {name_or_ip_address}
To generate a core dump of the target system, enter the file command and use the -c option to specify where to store the resulting file.
(lldb)file -c /tmp/mycorefile
The lldb tool automatically searches any spotlight-indexed directories and the /Library/Developer/KDKs/ directory on the local system for symbol information. You can specify the location of the kernel symbol files by including the path to the kernel file on the command line when you launch lldb. For example:
%lldb /Library/Developer/KDKs/<KDK Version>/System/Library/Kernels/kernel
Apple silicon-based Mac computers don’t support active kernel debugging. You may inspect the current state of the kernel when it is halted due to a panic or NMI. However, you cannot set breakpoints, continue code execution, step into code, step over code, or step out of the current instruction.
Finish Up Your Debugging Session
When you finish debugging the target device, quit lldb to disconnect the host from the target machine.
When you no longer need to debug the target device, return the device to normal operation:
1. Remove the boot args using the nvram tool:
⁃ sudo nvram -d boot-args
2. Re-enable SIP and restore your Boot Policy on Apple Silicon Macs or your Secure Boot policy on Intel Macs.
Installing Kernel and Kernel Extension Variants
The KDK includes several variants of the kernel binary and kernel extensions. These variants include additional assertions and error checking beyond what is present in the shipping version of the macOS kernel, and may be useful for debugging in various situations. Choose the variant that best suits your needs:
• The kernel (release) variant matches the shipping kernel for users.
• The kernel.development (development) variant is safe for everyday use during development, and has minimal performance overhead.
• The kernel.kasan (kasan) variant enables address sanitizer features.
When performing two-machine debugging, install these kernel variants on the target device.
Note: Apple silicon Macs don’t support the kernel and kernel extension variants from the KDK.
Install the Variants on an Intel-Based Mac
To install new kernel and kernel extension variants on the target device, perform the following steps:
Step 1: Install the KDK
Install this KDK on the target device.
Step 2: Modify the Security Configuration of Your Mac
Modify the security configuration of your Mac by disabling SIP and enabling permissive security:
1. Reboot your system in Recovery Mode.
2. If your device has the Apple T2 Security Chip, set the Secure Boot policy to “Medium Security”.
3. Launch Terminal and run the following commands to disable System Integrity Protection (SIP) and Authenticated Root protection:
⁃ csrutil disable
⁃ csrutil authenticated-root disable
4. Reboot your Mac computer.
Step 3: Identify the System Volume Disk Device Name
Run the mount command in Terminal to identify the devices of your system volume snapshot. Look for the device mounted at “/“, which identifies the system volume disk. In the following example, this disk is /dev/disk4s5s1.
/dev/disk4s5s1 on / (apfs, sealed, local, read-only, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk4s4 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk4s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
/dev/disk4s1 on /System/Volumes/Data (apfs, local, journaled, nobrowse)
To get the actual name of the system volume disk, remove the final “sX” from the device. In the preceding example, the name of the system volume disk is /dev/disk4s5.
Step 4: Mount a Live Version of the System Volume
Run the mount command in Terminal to mount the system volume disk to a temporary location. When running the mount command, always include the nobrowse mount option to prevent Spotlight from indexing the volume.
mkdir /Users/jappleseed/livemount
sudo mount -o nobrowse -t apfs /dev/disk4s5 /Users/jappleseed/livemount
Step 5: Add the Variant Files to the Live Mount
Add the kernel variant files to the newly mounted disk. The easiest way to copy the files is to copy the entire /System directory of the KDK into the /System directory of your mounted disk, as shown in the following example:
sudo ditto /Library/Developer/KDKs/<KDK Version>/System /Users/jappleseed/livemount/System
Step 6: Rebuild the Kernel Collections and Bless the Changes
Run kmutil in Terminal to rebuild the kernel collections for the variants you added to your mounted disk. Run bless to authorize booting from your modified kernels.
sudo kmutil install --volume-root /Users/jappleseed/livemount --update-all
sudo bless --folder /Users/jappleseed/livemount/System/Library/CoreServices --bootefi --create-snapshot
Step 7: Set the boot-args
Run the nvram tool in Terminal to add the following key to your boot args:
• kcsuffix — Set the value of this key to either development or kasan, based on which kernel variant you want to use. Omit this argument if you want the release kernel.
For example:
sudo nvram boot-args=“debug=0x44 kdp_match_name=en1 wdt=-1 kcsuffix=development”
Step 8: Reboot the Device
Upon rebooting, the selected kernel variant is active.
Remove the Variants
To remove all kernel variants from your Intel-based Mac, perform a software update, either to the current version of macOS, or to a newer version.
Re-enable System Integrity Protection, and restore full SecureBoot security.
In addition, remove the boot args you were using,
sudo nvram -d boot-args
Configuring a Core Dump Server
You can use another Mac to capture core dumps from your system automatically over the network. This may be useful for kernel panics that occur early in the boot cycle, or when the kernel fails to write the core dump file to disk after a panic. You can use a core dump server simultaneously with two-machine debugging. Use the following terminology to refer to the Macs associated with core dumps:
- The target device is the Mac that generates the core dump file.
- The server device is the Mac that receives the core dump files.
Configure the Server Device
Step 1: Create a /PanicDumps Directory
Create a directory on the server, and configure it to be writable by any user. This directory is where the server stores the core dump files.
mkdir /Users/jappleseed/dumps
 chmod 1777 /Users/jappleseed/dumps
Edit the /etc/synthetic.conf file to create a link named /PanicDumps that can be modified by any user.
PanicDumps Users/jappleseed/dumps
For more information, see the synthetic.conf(5) man page.
Step 2: Reboot the Device
You must reboot the device before the new /PanicDumps link appears.
Step 3: Load the kdumpd Launch Daemon
Run the launchctl command in Terminal to load the kdumpd launch daemon. This service listens for incoming core dumps and writes them to /PanicDumps.
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.kdumpd.plist
Configure the Target Device
The same compatibility requirements apply to the target device as for two-machine debugging. You must also configure the target device as if you’re using it for two-machine debugging.
After performing those configuration steps, perform the following additional steps:
Step 1: Set additional boot-args
Add the following keys to your boot args:
• debug=0xc44—Tells the kernel to create a core dump when a panic or NMI occurs.
• _panicd_ip=10.0.40.2—Set the value of this key to the IP address of the server device.
sudo nvram boot-args=“debug=0xc44 kdp_match_name=en1 wdt=-1 _panicd_ip=10.0.40.2”
Step 2: Reboot the Device
After you reboot the target device, it sends core dumps to the server in the following situations:
• If the target device panics.
• If you trigger an NMI on the target device.
Core dumps can be very large, so it may take some time for the core dump to transfer over the network.
Finish Up
When you no longer want to gather core dumps from the target device, return that device to normal operation. To do that, reenable SIP and use the nvram tool to remove any boot args:
sudo nvram -d boot-args
When you no longer wish to capture core dumps on the server device, remove the PanicDumps entry from synthetic.conf and reboot the server. The reboot also stops the kdumpd launch daemon.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment