Apple Silicon supports kernel debugging, but there are some limitations.
Limitations:
- No known way to switch between kernel variants (e.g.
.development
, etc.) - Active debugging is not supported, but you can still trigger an NMI with the power button.
This is somewhat straightforward and follows the general guide outlined in the
ReadMe.pdf
file contained inside the KDK. The complications arise once you're
inside the debugger.
Note: SIP needs to be disabled to set NVRAM boot arguments
There are multiple ways to get a connection between your host and target machine, but the cheapest option is to purchase a "Thunderbolt 3 (USB-C) to Thunderbolt 2 Adapter" and "Thunderbolt to Gigabit Ethernet Adapter". Then connect an ethernet cable between the target and host (can use a USB-C to ethernet adapter on the host end). A regular ethernet to USB-C adapter on the target will not work.
Once both machines are connected, find the name of the networking interface in
ifconfig
and set the boot-args
accordingly:
$ sudo nvram boot-args="debug=0x44 kdp_match_name=enX wdt=-1"
Reboot and record the address of the target on using ifconfig
(on the interface
used for debugging) then trigger a panic on the target machine. On the host machine run lldb
and kdp-remote
with the address of the target machine:
$ lldb
(lldb) kdp-remote 169.254.XXX.XXX
Once you are done with debugging, clear the boot-args
with
sudo nvram -d boot-args
If on any memory read
or x
(x
is an alias for memory read
) you are getting
error: kdp read memory failed
Your lldb
is broken. Known broken versions include:
- lldb-1200.0.41 (Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8))
This is due to a bug where lldb
attempts to correct the base address to use iOS
semantics. The heap on iOS is 0xFFFFFFE0xxxxxxxx
whereas on ASi it's 0xFFFFFE0xxxxxxxx
(notice the missing F
).
This is apparent if you open a coredump and inspect an address:
(lldb) x/x 0xffffe00010204000
error: core file does not contain 0xffffffe010204000
To workaround this issue on a broken lldb
use p
to evaluate expressions, e.g.:
p *(uint32_t*) 0xfffffe0010204000
This will not use memory read
and will therefore work as intended. As well,
amend all scripts in the KDK distribution that use the iOS address with the ASi
one:
if name == 'VM_MIN_KERNEL_ADDRESS':
if self.arch == 'x86_64':
return unsigned(0xFFFFFF8000000000)
elif self.arch.startswith('arm64'):
- return unsigned(0xffffffe000000000)
+ return unsigned(0xfffffe000000000)
else:
return unsigned(0x80000000)
You can alternatively debug the system by writing coredumps to a remote server and inspect them afterwards. Note that coredumps are typically very large uncompressed (e.g.: 700mb+) so ensure that there is adequate space on the server before continuing.
Connect both machines using the same setup in Two-Machine Debugging Setup and record the IP address of the server running
kdumpd
. Then, on the panicking machine, set the boot-args
as follows:
$ $ sudo nvram boot-args="debug=0xc44 kdp_match_name=enX wdt=-1 _panicd_ip=169.254.XXX.XXX"
On the server, create a location for the coredumps and start kdumpd
:
$ sudo mkdir /PanicDumps
$ sudo chown root:wheel /PanicDumps
$ sudo chmod 1777 /PanicDumps
You can either start the daemon:
$ sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.kdumpd.plist
Or you can run it in the foreground:
$ kdumpd -w /PanicDumps
Once the panicking machine panics, the coredump will be written gzipped to
/PanicDumps
. gunzip
it and then load it in lldb
with
$ lldb /System/Library/Kernels/kernel.release.t8101 --core core-xnu-XXX
See bugs before continuing.
Once done creating crash dumps, stop the daemon or kill the foreground kdumpd
process and wipe the boot-args
with sudo nvram -d boot-args
.