
Kernel híbrido que combina Mach, FreeBSD e IOKit para macOS e iOS. Fornece serviços principais do sistema operacional, framework de drivers e aplicação de política de segurança nas arquiteturas x86_64 e ARM64.
O kernel XNU faz parte do sistema operacional Darwin, utilizado nos sistemas operacionais macOS e iOS. XNU é um acrônimo para X is Not Unix. XNU é um kernel híbrido que combina o kernel Mach desenvolvido na Universidade Carnegie Mellon com componentes do FreeBSD e uma API C++ para escrever drivers chamada IOKit. XNU executa em x86_64 e ARM64 para configurações de processador único e multiprocessador.
config - configurações para APIs exportadas para arquitetura e plataforma suportadasSETUP - Conjunto básico de ferramentas usadas para configurar o kernel, versionamento e gerenciamento de kextsymbol.EXTERNAL_HEADERS - Cabeçalhos obtidos de outros projetos para evitar ciclos de dependência durante a compilação. Esses cabeçalhos devem ser sincronizados regularmente quando o código fonte for atualizado.libkern - código da biblioteca C++ IOKit para manipulação de drivers e kexts.libsa - código de inicialização do kernel para arranquelibsyscall - interface de biblioteca de syscall para programas em espaço de usuáriolibkdd - código fonte para biblioteca de usuário para análise de dados do kernel, como dados fragmentados do kernel.makedefs - regras e definições de nível superior para a compilação do kernel.osfmk - subsistemas baseados no kernel Machpexpert - código específico de plataforma, como tratamento de interrupções, atômicos, etc.security - interfaces de política de verificação de acesso obrigatório e implementação relacionada.bsd - código dos subsistemas BSDtools - Um conjunto de utilitários para teste, depuração e perfilamento do kernel.DEVELOPMENTO sistema de compilação do xnu pode construir o kernel com base nas variáveis KERNEL_CONFIGS e ARCH_CONFIGS como argumentos.
Aqui está a sintaxe:```text
make SDKROOT= ARCH_CONFIGS= KERNEL_CONFIGS=
Onde:
* `<sdkroot>`: caminho para o SDK do macOS no disco. (padrão é `/`)
* `<variant>`: pode ser `debug`, `development`, `release`, `profile` e configura flags de compilação e asserções em todo o código do kernel.
* `<arch>`: pode ser uma arquitetura válida para compilar. (Ex.: `X86_64`)
Para compilar um kernel para a mesma arquitetura do SO em execução, basta digitar```text
make SDKROOT=macosx.internal
Além disso, há suporte para configurar arquiteturas através de ARCH_CONFIGS e configurações de kernel com 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 padrão, a arquitetura é definida como a arquitetura da máquina de build, e a configuração padrão do kernel é definida para compilar para `DEVELOPMENT`.
Isso também criará uma imagem inicializável, kernel.[config], e um binário do kernel com símbolos, kernel.[config].unstripped.
Para instalar o kernel em um DSTROOT, use o alvo `install_kernels`:```text
make install_kernels DSTROOT=/tmp/xnu-dst
Para uma experiência de depuração do kernel mais satisfatória, com acesso a todas as variáveis e argumentos locais, mas sem todas as verificações extras do kernel DEBUG, adicione algo como o seguinte ao seu comando make:```text CFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2" CXXFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2"
Lembre-se de substituir `DEVELOPMENT` e `ARM64` pela build e plataforma apropriadas.
> Bandeiras Extras: Você pode passar bandeiras adicionais para o compilador C na linha de comando com a configuração de build `EXTRA_CFLAGS`. Essas bandeiras são anexadas às `CFLAGS` base, e o valor padrão para a configuração é uma string vazia.
>
> Esta configuração permite, por exemplo, ativar seletivamente código de depuração que é protegido por uma macro de pré-processador. Exemplo de uso...
>
> ```text
> make SDKROOT=macosx.internal PRODUCT_CONFIGS=j314s
> EXTRA_CFLAGS='-DKERNEL_STACK_MULTIPLIER=2'
> ```
* Para compilar com configuração de kernel RELEASE
```text
make KERNEL_CONFIGS=RELEASE SDKROOT=/path/to/SDK
```
### Compilando o Binário do Kernel FAT
Defina as arquiteturas no seu ambiente ou ao executar um comando make.```text
make ARCH_CONFIGS="X86_64" exporthdrs all
O sistema de compilação XNU pode opcionalmente gerar saída com formatação colorida. Para habilitar isso, você pode definir
a variável de ambiente XNU_LOGCOLORS como y, ou passar LOGCOLORS=y para o comando make.
A versão do xnu é derivada do SDK ou KDK lendo o CFBundleVersion
do arquivo System/Library/Extensions/System.kext/Info.plist deles.
Isso pode ser personalizado definindo a variável RC_DARWIN_KERNEL_VERSION no
ambiente ou na linha de comando do make.
Veja doc/building/xnu_version.md para mais detalhes.
Por padrão, um repositório de informações de depuração DWARF é criado durante a fase de instalação; este é um "bundle" chamado kernel.development.<variant>.dSYM Para selecionar o formato mais antigo de informações de depuração STABS (onde as informações de depuração são incorporadas na imagem kernel.development.unstripped), defina a variável de ambiente BUILD_STABS.```sh export BUILD_STABS=1 make
## Construindo KernelCaches
Para testar o kernel xnu, você precisa construir um kernelcache que ligue os kexts e o kernel em uma única imagem inicializável.
Para construir um kernelcache, você pode usar os seguintes mecanismos:
* Usando a geração automática de kernelcache com `kextd`.
O daemon kextd fica monitorando alterações no diretório `/System/Library/Extensions`.
Então você pode configurar um novo kernel como
```text
cp BUILD/obj/DEVELOPMENT/X86_64/kernel.development /System/Library/Kernels/
touch /System/Library/Extensions
ps -e | grep kextd
```
* Invocando manualmente o `kextcache` para construir um novo kernelcache.
```text
kextcache -q -z -a x86_64 -l -n -c /var/tmp/kernelcache.test -K /var/tmp/kernel.test /System/Library/Extensions
```
## Inicializando um KernelCache em uma máquina alvo
O kernel de desenvolvimento e o iBoot suportam a configuração de argumentos de inicialização para que possamos inicializar com segurança em um kernel de teste e, se algo der errado, cair com segurança no kernelcache usado anteriormente.
A seguir estão os passos para obter tal configuração:
1. Crie o cache do kernel usando o comando kextcache como `/kernelcache.test`
2. Copie as configurações de inicialização existentes para um arquivo alternativo
```sh
cp /Library/Preferences/SystemConfiguration/com.apple.Boot.plist /next_boot.plist
```
3. Atualize o kernelcache e os boot-args para sua configuração
```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. Copie o novo config para `/Library/Preferences/SystemConfiguration/`
```sh
cp /next_boot.plist /Library/Preferences/SystemConfiguration/boot.plist
```
5. Abençoe o volume com as novas configurações.
```text
sudo -n bless --mount / --setBoot --nextonly --options "config=boot"
```
A flag `--nextonly` especifica que use as configurações `boot.plist` apenas para uma inicialização.
Então, se o kernel panicar, você pode reiniciar facilmente e recuperar o kernel original.
## Criando tags e cscope
Configure seu ambiente de build e, a partir do diretório raiz, execute:
make tags # isso construirá ctags e etags em um volume sensível a maiúsculas/minúsculas, apenas ctags em volumes insensíveis
make TAGS # isso construirá etags
make cscope # isso construirá o banco de dados cscope
## Instalando Novos Arquivos de Cabeçalho do XNU
O XNU instala arquivos de cabeçalho nos seguintes locais -
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` é usado por extensões de kernel.\
O `System.framework`, `/usr/include` e `/usr/local/include` são usados por aplicativos de nível de usuário. \
`IOKit.framework` é usado por clientes de espaço de usuário do IOKit. \
`/System/DriverKit/usr/include` é usado por drivers de espaço de usuário. \
Os arquivos de cabeçalho em `PrivateHeaders` do framework estão disponíveis apenas para **Desenvolvimento Interno da Apple**.
O diretório que contém o arquivo de cabeçalho deve ter um Makefile que
cria a lista de arquivos que devem ser instalados em diferentes locais.
Se você está adicionando o primeiro arquivo de cabeçalho em um diretório, precisará
criar um Makefile similar a `xnu/bsd/sys/Makefile`.
Adicione seu arquivo de cabeçalho à lista de arquivos correta, dependendo de onde você deseja
instalá-lo. Os locais padrão onde os arquivos de cabeçalho são instalados
de cada lista de arquivos são -
a. `DATAFILES` : Para disponibilizar o arquivo de cabeçalho no nível de usuário -
`$(DSTROOT)/usr/include`
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
b. `DRIVERKIT_DATAFILES` : Para disponibilizar o arquivo de cabeçalho para drivers de espaço de usuário do DriverKit -
`$(DSTROOT)/System/DriverKit/usr/include`
c. `PRIVATE_DATAFILES` : Para disponibilizar o arquivo de cabeçalho para uso interno da Apple no
nível de usuário -
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
d. `EMBEDDED_PRIVATE_DATAFILES` : Para disponibilizar o arquivo de cabeçalho no nível de
usuário para macOS como `EXTRA_DATAFILES`, mas para uso interno da Apple no nível de usuário
para sistemas embarcados como `EXTRA_PRIVATE_DATAFILES` -
`$(DSTROOT)/usr/include` (`EXTRA_DATAFILES`)
`$(DSTROOT)/usr/local/include` (`EXTRA_PRIVATE_DATAFILES`)
e. `KERNELFILES` : Para disponibilizar o arquivo de cabeçalho no nível de kernel -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers`
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
f. `PRIVATE_KERNELFILES` : Para disponibilizar o arquivo de cabeçalho para uso interno da Apple
para extensões de kernel -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
g. `MODULEMAPFILES` : Para disponibilizar o arquivo de mapa de módulo no nível de usuário -
`$(DSTROOT)/usr/include`
h. `PRIVATE_MODULEMAPFILES` : Para disponibilizar o arquivo de mapa de módulo para uso
interno da Apple no nível de usuário -
`$(DSTROOT)/usr/local/include`
i. `LIBCXX_DATAFILES` : Para disponibilizar o arquivo de cabeçalho para clientes libcxx no kernel:
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot`
j. `EXCLAVEKIT_DATAFILES` : Para disponibilizar o arquivo de cabeçalho para uso interno da Apple
no SDK ExclaveKit -
`$(DSTROOT)/System/ExclaveKit/usr/include`
k. `EXCLAVECORE_DATAFILES` : Para disponibilizar o arquivo de cabeçalho para uso interno da Apple
no SDK ExclaveCore -
`$(DSTROOT)/System/ExclaveCore/usr/include`
O Makefile combina as listas de arquivos mencionadas acima em diferentes
listas de instalação que são usadas pelo sistema de build para instalar os arquivos de cabeçalho. Existem
dois tipos de listas de instalação: dependentes de máquina e independentes de máquina.
Essas listas são indicadas pela presença de `MD` e `MI` na configuração de
build, respectivamente. Se o seu cabeçalho é específico de arquitetura, você deve
usar uma lista de instalação dependente de máquina (por exemplo, `INSTALL_MD_LIST`). Se o seu cabeçalho
deve ser instalado para todas as arquiteturas, você deve usar uma
lista de instalação independente de máquina (por exemplo, `INSTALL_MI_LIST`).
Se a lista de instalação que você deseja não existir, crie-a
adicionando as listas de arquivos apropriadas. As listas de instalação padrão, suas
listas de arquivos membros e seus locais padrão são descritos abaixo -
a. `INSTALL_MI_LIST`, `INSTALL_MODULEMAP_MI_LIST` : Instala arquivos de cabeçalho e mapa de módulo
em um local que está disponível para todos no nível de usuário.
Locais -
$(DSTROOT)/usr/include
Definição -
INSTALL_MI_LIST = ${DATAFILES}
INSTALL_MODULEMAP_MI_LIST = ${MODULEMAPFILES}
b. `INSTALL_DRIVERKIT_MI_LIST` : Instala o arquivo de cabeçalho em um local que está
disponível para drivers de espaço de usuário do DriverKit.
Locais -
$(DSTROOT)/System/DriverKit/usr/include
Definição -
INSTALL_DRIVERKIT_MI_LIST = ${DRIVERKIT_DATAFILES}
c. `INSTALL_MI_LCL_LIST`, `INSTALL_MODULEMAP_MI_LCL_LIST` : Instala arquivos de cabeçalho e
mapa de módulo em um local que está disponível para uso interno da Apple no nível de usuário.
Locais -
$(DSTROOT)/usr/local/include
Definição -
INSTALL_MI_LCL_LIST =
INSTALL_MODULEMAP_MI_LCL_LIST = ${PRIVATE_MODULEMAPFILES}
d. `INSTALL_IF_MI_LIST` : Instala o arquivo de cabeçalho em um local que está disponível
para todos para clientes de espaço de usuário do IOKit.
Locais -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
Definição -
INSTALL_IF_MI_LIST = ${DATAFILES}
e. `INSTALL_IF_MI_LCL_LIST` : Instala o arquivo de cabeçalho em um local que está
disponível para uso interno da Apple para clientes de espaço de usuário do IOKit.
Locais -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
Definição -
INSTALL_IF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
f. `INSTALL_SF_MI_LCL_LIST` : Instala o arquivo de cabeçalho em um local que está disponível
para uso interno da Apple no nível de usuário.
Locais -
$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
Definição -
INSTALL_SF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
g. `INSTALL_KF_MI_LIST` : Instala o arquivo de cabeçalho em um local que está disponível
para todos para extensões de kernel.
Locais -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
Definição -
INSTALL_KF_MI_LIST = ${KERNELFILES}
h. `INSTALL_KF_MI_LCL_LIST` : Instala o arquivo de cabeçalho em um local que está
disponível para uso interno da Apple para extensões de kernel.
Locais -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
Definição -
INSTALL_KF_MI_LCL_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
i. `EXPORT_MI_LIST` : Exporta o arquivo de cabeçalho para todo o xnu (bsd/, osfmk/, etc.)
apenas para compilação. Não instala nada no SDK.
Definição -
EXPORT_MI_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
j. `INSTALL_KF_LIBCXX_MI_LIST` : Instala o arquivo de cabeçalho para suporte libc++ no kernel.
Locais -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot
Definição -
INSTALL_KF_LIBCXX_MI_LIST = ${LIBCXX_DATAFILES}
k. `INSTALL_EXCLAVEKIT_MI_LIST` : Instala o arquivo de cabeçalho em um local que está
disponível para uso interno da Apple para ExclaveKit.
Locais -
$(DSTROOT)/System/ExclaveKit/usr/include
Definição -
INSTALL_EXCLAVEKIT_MI_LIST = ${EXCLAVEKIT_DATAFILES}
l. `INSTALL_EXCLAVECORE_MI_LIST` : Instala o arquivo de cabeçalho em um local que está
disponível para uso interno da Apple para ExclaveCore.
Locais -
$(DSTROOT)/System/ExclaveCore/usr/include
Definição -
INSTALL_EXCLAVECORE_MI_LIST = ${EXCLAVECORE_DATAFILES}
Se você deseja instalar o arquivo de cabeçalho em um subdiretório dos caminhos
descritos em (1), especifique o nome do diretório usando duas variáveis
`INSTALL_MI_DIR` e `EXPORT_MI_DIR` da seguinte forma -```text
INSTALL_MI_DIR = dirname
EXPORT_MI_DIR = dirname
Se você deseja instalar o arquivo de mapa de módulo em um subdiretório, especifique o nome do diretório usando a variável INSTALL_MODULEMAP_MI_DIR da seguinte forma -```text
INSTALL_MODULEMAP_MI_DIR = dirname
Um único arquivo de cabeçalho pode existir em diferentes locais usando as etapas
mencionadas acima. No entanto, pode não ser desejável disponibilizar todo o código
do arquivo de cabeçalho em todos os locais. Por exemplo, você
deseja exportar uma função apenas para o nível do kernel, mas não para o nível do usuário.
Você pode usar a diretiva de pré-processador da linguagem C (#ifdef, #endif, #ifndef)
para controlar o texto gerado antes de um arquivo de cabeçalho ser instalado. O kernel
inclui o código apenas se a macro condicional for VERDADEIRA e remove o
código para condições FALSAS do arquivo de cabeçalho.
Algumas macros pré-definidas e suas descrições são -
1. `PRIVATE` : Se definida, as definições incluídas são consideradas Interfaces Privadas
do Sistema. Elas são visíveis dentro do xnu e
expostas nos cabeçalhos de usuário/kernel instalados nas seções "PrivateHeaders"
do AppleInternal dos frameworks System e Kernel.
2. `KERNEL_PRIVATE` : Se definida, o código incluído está disponível para todo o kernel
xnu e extensões de kernel internas da Apple e é omitido dos cabeçalhos
de usuário.
3. `BSD_KERNEL_PRIVATE` : Se definida, o código incluído é visível exclusivamente
dentro do módulo xnu/bsd.
4. `MACH_KERNEL_PRIVATE`: Se definida, o código incluído é visível exclusivamente
dentro do módulo xnu/osfmk.
5. `XNU_KERNEL_PRIVATE`: Se definida, o código incluído é visível exclusivamente
dentro do xnu.
6. `KERNEL` : Se definida, o código incluído está disponível dentro do xnu e extensões
de kernel e não é visível em arquivos de cabeçalho de nível de usuário. Apenas os
arquivos de cabeçalho instalados nos seguintes caminhos terão o código -
```text
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
```
7. `DRIVERKIT`: Se definida, o código incluído é visível exclusivamente nos
cabeçalhos do DriverKit SDK usados por drivers de espaço de usuário.
8. `EXCLAVEKIT`: Se definida, o código incluído é visível exclusivamente nos
cabeçalhos do ExclaveKit SDK.
9. `EXCLAVECORE`: Se definida, o código incluído é visível exclusivamente nos
cabeçalhos do ExclaveCore SDK.
10. `MODULES_SUPPORTED` Se definida, o código incluído é visível exclusivamente
em locais que suportam módulos/Swift (ou seja, não em frameworks System ou Kernel).
## Convenção de nomes de arquivos de cabeçalho da VM
Os cabeçalhos da VM seguem as seguintes convenções de nomenclatura:
* `*_internal.h` cabeçalhos contêm componentes do subsistema VM apenas para uso pelo código VM.
* `*_xnu.h` cabeçalhos contêm componentes do subsistema VM apenas para uso por outro código xnu.
* `*.h` cabeçalhos contêm componentes do subsistema VM exportados para kexts.
* `vm_iokit.h` cabeçalho contém componentes do subsistema VM exportados para o subsistema iokit.
* `vm_ubc.h` cabeçalho contém componentes do subsistema VM exportados para o subsistema ubc.
## Convenção de nomes de arquivos de mapa de módulo
No caso simples, um subdiretório de `usr/include` ou `usr/local/include`
pode ser representado por um módulo independente. Quando for esse o caso, defina
`INSTALL_MODULEMAP_MI_DIR` como `INSTALL_MI_DIR` e instale um arquivo `module.modulemap`
lá. `module.modulemap` é usado mesmo para módulos privados em
`usr/local/include`; `module.private.modulemap` não é usado. Atenção: para
permanecer no caso simples, o nome do módulo precisa ser exatamente o mesmo que
o nome do diretório. Se isso não for possível, o método a seguir precisará ser aplicado.
`xnu` contribui para os módulos definidos em CoreOSModuleMaps instalando
arquivos de mapa de módulo provenientes de `usr/include/module.modulemap` e
`usr/local/include/module.modulemap`. A convenção de nomenclatura para os
arquivos de mapa de módulo do `xnu` é a seguinte.
a. Idealmente, o arquivo de mapa de módulo cobre um diretório inteiro. Um arquivo de mapa
de módulo cobrindo `usr/include/a/b/c` seria nomeado `a_b_c.modulemap`.
`usr/local/include/a/b/c` seria `a_b_c_private.modulemap`.
b. Alguns cabeçalhos são especiais e exigem seu próprio módulo. Nesse caso,
o arquivo de mapa de módulo seria nomeado de acordo com o módulo que define.
Um arquivo de mapa de módulo definindo o módulo `One.Two.Three` seria nomeado
`one_two_three.modulemap`.
## Compilação Condicional
`xnu` oferece os seguintes mecanismos para compilar código condicionalmente:
1. *Características da CPU* Se o código que você está protegendo possui características
específicas que variarão apenas com base na arquitetura da CPU alvo, use esta opção. Prefira verificar
por características da arquitetura (por exemplo, `__LP64__`, `__LITTLE_ENDIAN__`, etc.).
2. *Novos Recursos* Se o código que você está protegendo, em conjunto,
implementa um recurso, você deve definir um novo recurso em `config/MASTER`
e usar o token de pré-processador `CONFIG` resultante (por exemplo, para um recurso
chamado `config_virtual_memory`, verifique `#if CONFIG_VIRTUAL_MEMORY`).
Essa prática garante que recursos existentes possam ser trazidos para outras
plataformas simplesmente alterando uma chave de recurso.
3. *Recursos Existentes* Você pode usar recursos existentes se o seu código estiver
fortemente vinculado a eles (por exemplo, use `SECURE_KERNEL` se o seu código implementar
uma nova funcionalidade que é exclusivamente relevante para o kernel confiável e
atualizar a definição/compreensão do que significa ser um kernel confiável).
Recomenda-se evitar compilar com base na plataforma alvo. `xnu`
não define as macros de plataforma de `TargetConditionals.h`
(`TARGET_OS_OSX`, `TARGET_OS_IOS`, etc.).
## Depuração do XNU
Por padrão, o kernel reinicia em caso de pânico.
Esse comportamento pode ser substituído pelo argumento de inicialização `debug` -- `debug=0x14e` fará com que um pânico aguarde a conexão de um depurador.
Para iniciar um kernel de forma que possa ser depurado por uma máquina conectada, substitua o argumento de inicialização `kdp_match_name` pela interface `ifconfig` apropriada.
Depuração Ethernet, Thunderbolt e serial são suportadas, dependendo do hardware.
Use o LLDB para depurar o kernel:```text
xcrun -sdk macosx lldb <path-to-unstripped-kernel>
(lldb) gdb-remote [<host-ip>:]<port>
A informação de depuração para o kernel (dSYM) vem com um conjunto de macros para suportar a depuração do kernel. Para carregar estas macros automaticamente ao anexar ao kernel, adicione o seguinte ao ~/.lldbinit:
settings set target.load-script-from-symbol-file true
```
`tools/lldbmacros` contém o código-fonte para esses comandos.
Veja o README nesse diretório para seu uso, ou use a ajuda integrada do LLDB com:```text
(lldb) help showcurrentstacks
```