For low-level iOS/Mac developers, the best way to explore the xNU kernel implementation is to debug the source code and track its implementation. Therefore, it is necessary to debug the XNU kernel. This article mainly combs the process of setting up the kernel debugging environment to start the year
An overview of the
Apple provides a kernel debugging protocolKDP(Kernel Debug Protocol)
To support remote debugging, the protocol is based onUDP
The protocol allows the debugger to send commands to the kernel and receive returned results and exception notifications. This article will be based on the latest system versionOS X10.15.6
, to build a kernel debugging environment to track the kernel process, the specific kernel version is as follows:
The preparatory work
Debugging the kernel will inevitably cause panic. Therefore, the best way is to run the system on a VIRTUAL machine (VM) that supports snapshot management to facilitate environment saving. Commonly used VMWare and Paralles, but the author uses Paralles to build the environment process there are some problems (will be explained later), so, it is recommended to use VMWare to install the system.
Installing a VM
You can download the latest version of the MacOS image from the App Store. The specific installation process is not described here, please Google it.
Download the toolkit and install it
Kit includes LLDB + KDK (Kernel Debug Kit), including KDK download address: developer.apple.com/download/mo… The specific version to be downloaded must meet the requirements of the latest system version. You can run the following command to view the system version
sw_vers |grep BuildVersion
Copy the code
As shown in the figure below:Or view it by “System Report -> Software”, as shown in the picture below:However, the official website did not find a fully matched version, but it has been verified that you can use the latest tool package, the specific version is:Kernel Debug Kit 10.15.6 build 19G73
.
The debugging tool package must be installed to debug hosts and VMS. After the installation is complete in the/Library/Developer/KDKs/KDK_10. 15.6 _19G73. KDK/System/Library/Kernels directory to see the kernel binary files, Xcode debug symbols. DSYM, as well as the kernel. Develo Pment kernel debugging file.
downloadxnu
The source code
Run the uname -v command to check that the version 10.15.6 is XNU-6153.141.1. Therefore, download the corresponding source code from apple for subsequent debugging of the XNU source code.
Shut down the SIP
When debugging hosts and VMS, disable SIP system integrity protection as follows:
- The system starts quickly
Command+R
Until the Apple icon appears; - Open the utility’s terminal and type
csrutil disable
To disable and restart the system;
After the system restarts, it can passcsrutil status
Check the closed status. The correct status is as follows:
debugging
The kernel to replace
The vm needs to assign the kernel debugging version in the KDK installation directory to /System/Library/Kernels:
Cp/Library/Developer/KDKs/KDK_10. 15.6 _19G73. KDK/System/Library/Kernels/kernel development/System/Library/KernelsCopy the code
However,Catalina
After the version, the hard disk is divided into the read-only part and the data part. Because the kernel directory is in the read-only directory, you need to change the file permissionsudo chmod
It can’t be modified. It can be passedmount
Tool to temporarily change the permission (the permission will be restored after the restart), as follows:
sudo mount -uw /
Copy the code
Set the NVRAM boot parameter boot-args
To set the VM to debug mode, run the following command to set boot-args using nvRAM
nvram boot-args="debug=0x141 kext-dev-mode=1 kcsuffix=development pmuflags=1 -v"
Copy the code
NVRAM: Error setting variable – ‘boot-args’; (iokit/ Common) General Error: Attempts to set recovery mode are invalid.
The following figure shows the debugging bits
For details, see the Building and Debugging Kernels
debug=0x145
, including0x01
Because the system will wait for the debugger to mount after startup,0x04
Is triggered by a keyNMI (Non-Maskable Interrupt)
Unmasked interrupts are used to trigger the debug state so that it can be entered at any time. But the default VM group bond to trigger unmasked interrupts asCommand-Option-Control-Shift-Escape
It’s too long. You can go throughVMWare
As shown in the figure below:
kext-dev-mode=1
Allowed to load unsignedkext
kcsuffix=development
Specifies to load the copy abovekernel.development
pmuflags=1
Turn off the watchdog timer-v
The kernel loading information is displayed
Network configuration pits:
- If you are using FireWire cables through the physical FireWire port (on older Mac machines), see Debugging macOS Kernel For Fun
- If the VM is configured with two nics, for example
host-only
And the defaultNAT
, it needs to passkdp_match_name
Option to specify the nic mode, seeMac kernel extension development
Clear the Kext cache
The command is as follows:
sudo kextcache -invalidate /
Copy the code
Let the virtual machine systemkext cache
No, use the new kernel to debug and restart the system, and you will enter debug mode, as shown below:
LLDB mounting debugging
Debug host start LLDB and set goals for kernel debugging in KDK the directory file/Library/Developer/KDKs/KDK_10. 15.6 _19G73. KDK/System/Library/Kernels/kernel. The development, As follows:
$lldb(LLDB) target the create/Library/Developer/KDKs/KDK_10 _19G73. 15.6 KDK/System/Library/Kernels/kernel developmentCopy the code
If you encounter the following problems:
Execute the following commands as prompted:
command script import "/ Library/Developer/KDKs/KDK_10. 15.6 _19G73. KDK/System/Library/Kernels/kernel development. The dSYM/Contents/Resources/Python / kernel.py"
Copy the code
The following error is encountered:instructionspython
The version is wrong. It needs to be changedpython 2
, enter the following command as prompted:
defaults write com.apple.dt.lldb DefaultPythonVersion 2
Copy the code
Note: This command is not executed in LLDB
The successes are as follows:
Connecting to a VM
Kdp-remote XXX // XXX indicates the IP address of the VMCopy the code
After success, it is shown as the picture below:
xnu
The source code to debug
Debugging, LLDB will go/Library/Caches/com. Apple. XBS/Sources/xnu (without the directory is created) corresponding to the version of the directory to find the kernel source xnu – XXX, so put this directory can download the source of support in front of the xnu source code debugging.
In actual combat
Trace application crash throwMach
Exception conversion toSignal
Signal flow, specificMach
The process of exception and signal conversion is as follows:
Test code is as follows:
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#define BUF_LEN 1024
static void sig_int(int signo) {
printf("handler signo:%d \n", signo);
}
int main(int argc, char **argv) {
char buf[BUF_LEN] = {0};
// Process the signal
// The CTRL + C process terminates
if (signal(SIGINT, sig_int) == SIG_ERR) {
printf("signal error:%s \n", strerror(errno));
}
// A hardware exception is generated
intptr_t *ptr = NULL;
*ptr = 1;
return 0;
}
Copy the code
throughbreakpoint set -n xxx
Set the kernel functions that require breakpoints, as shown below:
The function call stack looks like this:
We can work togetherxnu
Source code to further trace the invocation process, such asthreadsignal
The function is shown in the figure below:
The detailed call process is not detailed here, mainly is clear how to trace xNU source code implementation process through kernel debugging.