
Kernel híbrido que combina Mach, FreeBSD y IOKit para macOS y iOS. Proporciona servicios centrales del SO, un marco de controladores y aplicación de políticas de seguridad en x86_64 y ARM64.
El kernel XNU es parte del sistema operativo Darwin para su uso en los sistemas operativos macOS e iOS. XNU es un acrónimo de X is Not Unix. XNU es un kernel híbrido que combina el kernel Mach desarrollado en la Universidad Carnegie Mellon con componentes de FreeBSD y una API en C++ para escribir controladores llamada IOKit. XNU se ejecuta en x86_64 y ARM64 tanto para configuraciones de un solo procesador como multiprocesador.
config - configuraciones para las APIs exportadas para la arquitectura y plataforma soportadas.SETUP - Conjunto básico de herramientas utilizadas para configurar el kernel, versionado y gestión de kextsymbol.EXTERNAL_HEADERS - Encabezados obtenidos de otros proyectos para evitar ciclos de dependencia al compilar. Estos encabezados deben sincronizarse regularmente cuando se actualiza la fuente.libkern - Código de la biblioteca IOKit en C++ para el manejo de controladores y kexts.libsa - código de arranque del kernel para inicio.libsyscall - interfaz de la biblioteca de syscall para programas de espacio de usuario.libkdd - fuente de la biblioteca de usuario para analizar datos del kernel como datos fragmentados del kernel.makedefs - reglas y definiciones de nivel superior para la compilación del kernel.osfmk - subsistemas basados en el kernel Mach.pexpert - código específico de la plataforma como manejo de interrupciones, atómicos, etc.security - interfaces de políticas de verificación de acceso obligatorio e implementación relacionada.bsd - código de subsistemas BSD.tools - conjunto de utilidades para probar, depurar y perfilar el kernel.DEVELOPMENTEl sistema de compilación de xnu puede compilar el kernel basándose en las variables KERNEL_CONFIGS y ARCH_CONFIGS como argumentos.
Aquí está la sintaxis:```text
make SDKROOT= ARCH_CONFIGS= KERNEL_CONFIGS=
Donde:
* `<sdkroot>`: ruta al SDK de macOS en el disco. (por defecto a `/`)
* `<variant>`: puede ser `debug`, `development`, `release`, `profile` y configura banderas de compilación y afirmaciones a lo largo del código del kernel.
* `<arch>`: puede ser una arquitectura válida para la cual compilar. (Ej. `X86_64`)
Para compilar un kernel para la misma arquitectura que el sistema operativo en ejecución, solo escriba```text
make SDKROOT=macosx.internal
Además, hay soporte para configurar arquitecturas mediante ARCH_CONFIGS y configuraciones de kernel con KERNEL_CONFIGS.```text
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS=DEVELOPMENT
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS="RELEASE DEVELOPMENT DEBUG"
> Nota: Por defecto, la arquitectura está configurada para la arquitectura de la máquina de compilación, y la configuración predeterminada del kernel está configurada para compilar para `DEVELOPMENT`.
Esto también creará una imagen de arranque, kernel.[config] y un binario del kernel con símbolos, kernel.[config].unstripped.
Para instalar el kernel en un DSTROOT, utiliza el objetivo `install_kernels`:```text
make install_kernels DSTROOT=/tmp/xnu-dst
Para una experiencia de depuración del kernel más satisfactoria, con acceso a todas las variables locales y argumentos, pero sin todas las comprobaciones adicionales del kernel DEBUG, agregue algo como lo siguiente a su comando make:```text CFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2" CXXFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2"
Recuerde reemplazar `DEVELOPMENT` y `ARM64` con la compilación y plataforma adecuadas.
> Banderas adicionales: Puede pasar banderas adicionales al compilador de C en la línea de comandos con la configuración de compilación `EXTRA_CFLAGS`. Estas banderas se agregan a las `CFLAGS` base, y el valor predeterminado para la configuración es una cadena vacía.
>
> Esta configuración le permite, por ejemplo, activar selectivamente código de depuración protegido por una macro de preprocesador. Ejemplo de uso...
>
> ```text
> make SDKROOT=macosx.internal PRODUCT_CONFIGS=j314s
> EXTRA_CFLAGS='-DKERNEL_STACK_MULTIPLIER=2'
> ```
* Para compilar con la configuración del kernel RELEASE
```text
make KERNEL_CONFIGS=RELEASE SDKROOT=/path/to/SDK
```
### Compilación del binario FAT del kernel
Defina las arquitecturas en su entorno o al ejecutar un comando make.```text
make ARCH_CONFIGS="X86_64" exporthdrs all
El sistema de compilación de XNU puede opcionalmente generar una salida de compilación con formato de color. Para habilitarlo, puede configurar la variable de entorno XNU_LOGCOLORS a y, o pasar LOGCOLORS=y al comando make.
La versión de xnu se deriva del SDK o KDK leyendo el CFBundleVersion
de su archivo System/Library/Extensions/System.kext/Info.plist.
Esto se puede personalizar configurando la variable RC_DARWIN_KERNEL_VERSION en
el entorno o en la línea de comandos de make.
Consulte doc/building/xnu_version.md para más detalles.
Por defecto, se crea un repositorio de información de depuración DWARF durante la fase de instalación; este es un "bundle" denominado kernel.development.<variant>.dSYM Para seleccionar el formato de información de depuración STABS más antiguo (donde la información de depuración está incrustada en la imagen kernel.development.unstripped), configure la variable de entorno BUILD_STABS.```sh export BUILD_STABS=1 make
## Construyendo KernelCaches
Para probar el kernel de xnu, necesitas construir un kernelcache que enlace los kexts y
kernel juntos en una única imagen arrancable.
Para construir un kernelcache puedes usar los siguientes mecanismos:
* Usando la generación automática de kernelcache con `kextd`.
El demonio kextd monitorea cambios en el directorio `/System/Library/Extensions`.
Así que puedes configurar un nuevo kernel como
```text
cp BUILD/obj/DEVELOPMENT/X86_64/kernel.development /System/Library/Kernels/
touch /System/Library/Extensions
ps -e | grep kextd
```
* Invocando manualmente `kextcache` para construir un nuevo kernelcache.
```text
kextcache -q -z -a x86_64 -l -n -c /var/tmp/kernelcache.test -K /var/tmp/kernel.test /System/Library/Extensions
```
## Arrancando un KernelCache en una máquina de destino
El kernel de desarrollo e iBoot soportan configurar argumentos de arranque para que podamos arrancar de manera segura en un kernel de prueba y, si algo sale mal, retroceder de manera segura al kernelcache usado anteriormente.
Los siguientes son los pasos para lograr dicha configuración:
1. Crear el kernel cache usando el comando kextcache como `/kernelcache.test`
2. Copiar las configuraciones de arranque existentes a un archivo alternativo
```sh
cp /Library/Preferences/SystemConfiguration/com.apple.Boot.plist /next_boot.plist
```
3. Actualizar el kernelcache y los boot-args para tu configuración
```sh
plutil -insert "Kernel Cache" -string "kernelcache.test" /next_boot.plist
plutil -replace "Kernel Flags" -string "debug=0x144 -v kernelsuffix=test " /next_boot.plist
```
4. Copiar la nueva configuración a `/Library/Preferences/SystemConfiguration/`
```sh
cp /next_boot.plist /Library/Preferences/SystemConfiguration/boot.plist
```
5. Bendecir el volumen con las nuevas configuraciones.
```text
sudo -n bless --mount / --setBoot --nextonly --options "config=boot"
```
La bandera `--nextonly` especifica que use las configuraciones de `boot.plist` solo para un arranque.
Así que si el kernel entra en pánico, puedes reiniciar y recuperar fácilmente el kernel original.
## Creando tags y cscope
Configura tu entorno de compilación y desde el directorio raíz, ejecuta:
make tags # esto construirá ctags y etags en un volumen con distinción de mayúsculas, solo ctags en uno sin distinción
make TAGS # esto construirá etags
make cscope # esto construirá la base de datos de cscope
## Instalando Nuevos Archivos de Cabecera desde XNU
XNU instala archivos de cabecera en las siguientes ubicaciones:
a. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
b. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
c. $(DSTROOT)/usr/include/
d. $(DSTROOT)/usr/local/include/
e. $(DSTROOT)/System/DriverKit/usr/include/
f. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
g. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
h. $(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
`Kernel.framework` es utilizado por las extensiones del kernel.\
`System.framework`, `/usr/include` y `/usr/local/include` son utilizados por aplicaciones a nivel de usuario.\
`IOKit.framework` es utilizado por los clientes de espacio de usuario de IOKit.\
`/System/DriverKit/usr/include` es utilizado por los controladores de espacio de usuario.\
Los archivos de cabecera en los `PrivateHeaders` de los frameworks solo están disponibles para **Apple Internal Development**.
El directorio que contiene el archivo de cabecera debe tener un Makefile que
cree la lista de archivos que deben instalarse en diferentes ubicaciones.
Si estás agregando el primer archivo de cabecera en un directorio, necesitarás
crear un Makefile similar a `xnu/bsd/sys/Makefile`.
Agrega tu archivo de cabecera a la lista de archivos correcta dependiendo de dónde quieras
instalarlo. Las ubicaciones predeterminadas donde se instalan los archivos de cabecera
desde cada lista de archivos son:
a. `DATAFILES` : Para que el archivo de cabecera esté disponible a nivel de usuario -
`$(DSTROOT)/usr/include`
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
b. `DRIVERKIT_DATAFILES` : Para que el archivo de cabecera esté disponible para controladores de espacio de usuario de DriverKit -
`$(DSTROOT)/System/DriverKit/usr/include`
c. `PRIVATE_DATAFILES` : Para que el archivo de cabecera esté disponible para Apple internal a
nivel de usuario -
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
d. `EMBEDDED_PRIVATE_DATAFILES` : Para que el archivo de cabecera esté disponible a nivel
de usuario para macOS como `EXTRA_DATAFILES`, pero para Apple internal a nivel de usuario
para sistemas operativos embebidos como `EXTRA_PRIVATE_DATAFILES` -
`$(DSTROOT)/usr/include` (`EXTRA_DATAFILES`)
`$(DSTROOT)/usr/local/include` (`EXTRA_PRIVATE_DATAFILES`)
e. `KERNELFILES` : Para que el archivo de cabecera esté disponible a nivel de kernel -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers`
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
f. `PRIVATE_KERNELFILES` : Para que el archivo de cabecera esté disponible para Apple internal
para extensiones del kernel -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
g. `MODULEMAPFILES` : Para que el archivo de mapa de módulos esté disponible a nivel de usuario -
`$(DSTROOT)/usr/include`
h. `PRIVATE_MODULEMAPFILES` : Para que el archivo de mapa de módulos esté disponible para Apple
internal a nivel de usuario -
`$(DSTROOT)/usr/local/include`
i. `LIBCXX_DATAFILES` : Para que el archivo de cabecera esté disponible para los clientes de libcxx dentro del kernel:
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot`
j. `EXCLAVEKIT_DATAFILES` : Para que el archivo de cabecera esté disponible para Apple internal
SDK de ExclaveKit -
`$(DSTROOT)/System/ExclaveKit/usr/include`
k. `EXCLAVECORE_DATAFILES` : Para que el archivo de cabecera esté disponible para Apple internal
SDK de ExclaveCore -
`$(DSTROOT)/System/ExclaveCore/usr/include`
El Makefile combina las listas de archivos mencionadas anteriormente en diferentes
listas de instalación que son utilizadas por el sistema de compilación para instalar los archivos de cabecera. Hay
dos tipos de listas de instalación: dependientes de la máquina e independientes de la máquina.
Estas listas se indican por la presencia de `MD` y `MI` en la configuración
de compilación, respectivamente. Si tu cabecera es específica de una arquitectura, entonces debes
usar una lista de instalación dependiente de la máquina (por ejemplo, `INSTALL_MD_LIST`). Si tu cabecera
debe instalarse para todas las arquitecturas, entonces debes usar una
lista de instalación independiente de la máquina (por ejemplo, `INSTALL_MI_LIST`).
Si la lista de instalación que te interesa no existe, créala
agregando las listas de archivos apropiadas. Las listas de instalación predeterminadas, sus
listas de archivos miembro y sus ubicaciones predeterminadas se describen a continuación:
a. `INSTALL_MI_LIST`, `INSTALL_MODULEMAP_MI_LIST` : Instala archivos de cabecera y mapas de módulos
en una ubicación que esté disponible para todos a nivel de usuario.
Ubicaciones -
$(DSTROOT)/usr/include
Definición -
INSTALL_MI_LIST = ${DATAFILES}
INSTALL_MODULEMAP_MI_LIST = ${MODULEMAPFILES}
b. `INSTALL_DRIVERKIT_MI_LIST` : Instala el archivo de cabecera en una ubicación que esté
disponible para controladores de espacio de usuario de DriverKit.
Ubicaciones -
$(DSTROOT)/System/DriverKit/usr/include
Definición -
INSTALL_DRIVERKIT_MI_LIST = ${DRIVERKIT_DATAFILES}
c. `INSTALL_MI_LCL_LIST`, `INSTALL_MODULEMAP_MI_LCL_LIST` : Instala archivos de cabecera y
mapas de módulos en una ubicación que esté disponible para Apple internal a nivel de usuario.
Ubicaciones -
$(DSTROOT)/usr/local/include
Definición -
INSTALL_MI_LCL_LIST =
INSTALL_MODULEMAP_MI_LCL_LIST = ${PRIVATE_MODULEMAPFILES}
d. `INSTALL_IF_MI_LIST` : Instala el archivo de cabecera en una ubicación que esté disponible
para todos para clientes de espacio de usuario de IOKit.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
Definición -
INSTALL_IF_MI_LIST = ${DATAFILES}
e. `INSTALL_IF_MI_LCL_LIST` : Instala el archivo de cabecera en una ubicación que esté
disponible para Apple internal para clientes de espacio de usuario de IOKit.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
Definición -
INSTALL_IF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
f. `INSTALL_SF_MI_LCL_LIST` : Instala el archivo de cabecera en una ubicación que esté disponible
para Apple internal a nivel de usuario.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
Definición -
INSTALL_SF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
g. `INSTALL_KF_MI_LIST` : Instala el archivo de cabecera en una ubicación que esté disponible
para todos para extensiones del kernel.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
Definición -
INSTALL_KF_MI_LIST = ${KERNELFILES}
h. `INSTALL_KF_MI_LCL_LIST` : Instala el archivo de cabecera en una ubicación que esté
disponible para Apple internal para extensiones del kernel.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
Definición -
INSTALL_KF_MI_LCL_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
i. `EXPORT_MI_LIST` : Exporta el archivo de cabecera a todo xnu (bsd/, osfmk/, etc.)
solo para compilación. No instala nada en el SDK.
Definición -
EXPORT_MI_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
j. `INSTALL_KF_LIBCXX_MI_LIST` : Instala el archivo de cabecera para soporte de libc++ dentro del kernel.
Ubicaciones -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot
Definición -
INSTALL_KF_LIBCXX_MI_LIST = ${LIBCXX_DATAFILES}
k. `INSTALL_EXCLAVEKIT_MI_LIST` : Instala el archivo de cabecera en una ubicación que esté
disponible para Apple internal para ExclaveKit.
Ubicaciones -
$(DSTROOT)/System/ExclaveKit/usr/include
Definición -
INSTALL_EXCLAVEKIT_MI_LIST = ${EXCLAVEKIT_DATAFILES}
l. `INSTALL_EXCLAVECORE_MI_LIST` : Instala el archivo de cabecera en una ubicación que esté
disponible para Apple internal para ExclaveCore.
Ubicaciones -
$(DSTROOT)/System/ExclaveCore/usr/include
Definición -
INSTALL_EXCLAVECORE_MI_LIST = ${EXCLAVECORE_DATAFILES}
Si deseas instalar el archivo de cabecera en un subdirectorio de las rutas
descritas en (1), especifica el nombre del directorio usando dos variables
`INSTALL_MI_DIR` y `EXPORT_MI_DIR` de la siguiente manera:```text
INSTALL_MI_DIR = dirname
EXPORT_MI_DIR = dirname
Si deseas instalar el archivo de mapa de módulos en un subdirectorio, especifica el nombre del directorio usando la variable INSTALL_MODULEMAP_MI_DIR de la siguiente manera -```text
INSTALL_MODULEMAP_MI_DIR = dirname
Un solo archivo de cabecera puede existir en diferentes ubicaciones usando los pasos mencionados anteriormente. Sin embargo, puede no ser deseable que todo el código del archivo de cabecera esté disponible en todas las ubicaciones. Por ejemplo, desea exportar una función solo a nivel de kernel pero no a nivel de usuario.
Puede usar la directiva de preprocesador del lenguaje C (`#ifdef`, `#endif`, `#ifndef`) para controlar el texto generado antes de que se instale un archivo de cabecera. El kernel solo incluye el código si la macro condicional es VERDADERA y elimina el código para condiciones FALSAS del archivo de cabecera.
Algunas macros predefinidas y sus descripciones son:
1. `PRIVATE` : Si está definida, las definiciones encerradas se consideran Interfaces Privadas del Sistema. Son visibles dentro de xnu y se exponen en las cabeceras de usuario/kernel instaladas dentro de las secciones "PrivateHeaders" de AppleInternal de los frameworks System y Kernel.
2. `KERNEL_PRIVATE` : Si está definida, el código encerrado está disponible para todo el kernel de xnu y las extensiones de kernel internas de Apple, y se omite de las cabeceras de usuario.
3. `BSD_KERNEL_PRIVATE` : Si está definida, el código encerrado es visible exclusivamente dentro del módulo xnu/bsd.
4. `MACH_KERNEL_PRIVATE`: Si está definida, el código encerrado es visible exclusivamente dentro del módulo xnu/osfmk.
5. `XNU_KERNEL_PRIVATE`: Si está definida, el código encerrado es visible exclusivamente dentro de xnu.
6. `KERNEL` : Si está definida, el código encerrado está disponible dentro de xnu y las extensiones de kernel, y no es visible en los archivos de cabecera de nivel de usuario. Solo los archivos de cabecera instalados en las siguientes rutas tendrán el código:
```text
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
```
7. `DRIVERKIT`: Si está definida, el código encerrado es visible exclusivamente en las cabeceras del SDK de DriverKit utilizadas por los controladores de espacio de usuario.
8. `EXCLAVEKIT`: Si está definida, el código encerrado es visible exclusivamente en las cabeceras del SDK de ExclaveKit.
9. `EXCLAVECORE`: Si está definida, el código encerrado es visible exclusivamente en las cabeceras del SDK de ExclaveCore.
10. `MODULES_SUPPORTED` Si está definida, el código encerrado es visible exclusivamente en ubicaciones que admiten módulos/Swift (es decir, no en los frameworks System o Kernel).
## Convención de nombres de archivos de cabecera de VM
Las cabeceras de VM siguen las siguientes convenciones de nomenclatura:
* Las cabeceras `*_internal.h` contienen componentes del subsistema VM solo para uso por parte del código de VM.
* Las cabeceras `*_xnu.h` contienen componentes del subsistema VM solo para uso por parte de otro código xnu.
* Las cabeceras `*.h` contienen componentes del subsistema VM exportados a kexts.
* La cabecera `vm_iokit.h` contiene componentes del subsistema VM exportados al subsistema iokit.
* La cabecera `vm_ubc.h` contiene componentes del subsistema VM exportados al subsistema ubc.
## Convención de nombres de archivos de mapa de módulos
En el caso simple, un subdirectorio de `usr/include` o `usr/local/include`
puede ser representado por un módulo independiente. Cuando esto ocurra, establezca
`INSTALL_MODULEMAP_MI_DIR` a `INSTALL_MI_DIR` e instale un archivo `module.modulemap`
allí. `module.modulemap` se usa incluso para módulos privados en
`usr/local/include`; `module.private.modulemap` no se usa. Advertencia: para
mantenerse en el caso simple, el nombre del módulo debe ser exactamente el mismo que
el nombre del directorio. Si eso no es posible, entonces se deberá aplicar el siguiente método.
`xnu` contribuye a los módulos definidos en CoreOSModuleMaps instalando
archivos de mapa de módulos que provienen de `usr/include/module.modulemap` y
`usr/local/include/module.modulemap`. La convención de nomenclatura para los
archivos de mapa de módulos de `xnu` es la siguiente.
a. Idealmente, el archivo de mapa de módulos cubre un directorio completo. Un archivo de mapa
de módulos que cubra `usr/include/a/b/c` se llamaría `a_b_c.modulemap`.
`usr/local/include/a/b/c` sería `a_b_c_private.modulemap`.
b. Algunas cabeceras son especiales y requieren su propio módulo. En ese caso,
el archivo de mapa de módulos se llamaría según el módulo que define.
Un archivo de mapa de módulos que defina el módulo `One.Two.Three` se llamaría
`one_two_three.modulemap`.
## Compilación Condicional
`xnu` ofrece los siguientes mecanismos para compilar código condicionalmente:
1. *Características de la CPU* Si el código que está protegiendo tiene
características específicas que variarán solo según la arquitectura de CPU
a la que se dirige, use esta opción. Prefiera verificar las características de la
arquitectura (por ejemplo, `__LP64__`, `__LITTLE_ENDIAN__`, etc.).
2. *Nuevas Funcionalidades* Si el código que está protegiendo, considerado en conjunto,
implementa una funcionalidad, debe definir una nueva funcionalidad en `config/MASTER`
y usar el token de preprocesador `CONFIG` resultante (por ejemplo, para una funcionalidad
llamada `config_virtual_memory`, verifique `#if CONFIG_VIRTUAL_MEMORY`).
Esta práctica garantiza que las funcionalidades existentes puedan ser llevadas a otras
plataformas simplemente cambiando un interruptor de funcionalidad.
3. *Funcionalidades Existentes* Puede usar funcionalidades existentes si su código está
fuertemente vinculado a ellas (por ejemplo, use `SECURE_KERNEL` si su código implementa
nueva funcionalidad que es exclusivamente relevante para el kernel de confianza y
actualiza la definición/comprensión de lo que significa ser un kernel de confianza).
Se recomienda evitar compilar según la plataforma de destino. `xnu`
no define las macros de plataforma de `TargetConditionals.h`
(`TARGET_OS_OSX`, `TARGET_OS_IOS`, etc.).
## Depuración de XNU
Por defecto, el kernel se reinicia en caso de pánico.
Este comportamiento se puede anular con el argumento de arranque `debug` -- `debug=0x14e` hará que un pánico espere a que un depurador se adjunte.
Para arrancar un kernel de modo que pueda ser depurado por una máquina conectada, anule el argumento de arranque `kdp_match_name` con la interfaz `ifconfig` apropiada.
Se admite depuración por Ethernet, Thunderbolt y serie, dependiendo del hardware.
Use LLDB para depurar el kernel:```text
xcrun -sdk macosx lldb <path-to-unstripped-kernel>
(lldb) gdb-remote [<host-ip>:]<port>
La información de depuración del kernel (dSYM) viene con un conjunto de macros para admitir la depuración del kernel. Para cargar estas macros automáticamente al adjuntarse al kernel, agregue lo siguiente a ~/.lldbinit:```text
settings set target.load-script-from-symbol-file true
`tools/lldbmacros` contiene el código fuente de estos comandos.
Consulte el README en ese directorio para su uso, o use la ayuda incorporada de LLDB con:```text
(lldb) help showcurrentstacks