Configurar a depuração no modo kernel QEMU usando EXDI
Este tópico descreve como configurar a depuração do modo kernel QEMU usando EXDI com o depurador Windows.
Para obter informações gerais sobre como definir a configuração e solucionar problemas de conexões EXDI, confira Configurar o transporte do depurador EXDI.
Usando o QEMU, o software de virtualização e emulação de máquina, é possível conectar-se a outros sistemas operacionais que servem como host, como o Linux. O próprio QEMU pode ser executado em várias arquiteturas, como x64 e Arm64. O servidor de depuração ExdiGdb também suporta outros processadores, por exemplo, é possível usar o WinDbg para depurar o QEMU em execução no x64, emulando o Arm64. O uso de EXDI também permite que a VM seja depurada por HW no início do processo de inicialização, mesmo antes de o sistema operacional ser carregado.
Observação
EXDI é uma forma avançada e especializada de depuração para ambientes específicos. Uma conexão KDNET padrão é mais fácil de configurar e é recomendada. Para configurar a depuração de rede automaticamente, confira Configurar a depuração automática do kernel de rede KDNET.
Servidor EXDI COM
EXDI é uma interface que permite estender o WinDbg adicionando suporte para depuradores de hardware (por exemplo, baseado em JTAG ou baseado em GdbServer). O diagrama abaixo ilustra a função do EXDI-GdbServer.
Importante
Como a EXDI não usa o protocolo KDNET, o depurador conectado tem significativamente menos informações sobre o que está sendo executado no PC e muitos comandos funcionarão de forma diferente ou podem não funcionar. O acesso a símbolos privados para o código que está sendo depurado pode ajudar o depurador a entender melhor a execução do código do sistema de destino. Para obter mais informações, confira Símbolos Públicos e Privados.
Configurar uma conexão do depurador com uma imagem do Windows no QEMU
Estas etapas descrevem como anexar a uma máquina virtual Windows x64 expondo um servidor GDB a um cliente Windbg (que usa o servidor EXDI COM), também em execução no Windows. Uma sessão RSP do GdbServer entre o ExdiGdbSrv.dll WinDbg (cliente do servidor GDB) e o servidor QEMU GDB é usada.
- Baixe e instale o QEMU no Windows.
- Configure uma imagem virtual do Windows QEMU de destino para iniciar com as configurações de rede e BIOS/UEFI necessárias para depuração.
- Inicie o ambiente QEMU, usando um script de ativação.
- Inicie o GdbServer no QEMU.
- Verifique a conectividade de rede e localize e registre o endereço IP da imagem de destino. (Endereço padrão IP do HOST de LocalHost e porta de 1234).
- Baixe e instale as ferramentas de depuração do Windows no sistema host.
- Inicie o WinDbg usando a linha de comando ou a interface do usuário para se conectar ao servidor EXDI.
- Use o WinDbg para depurar a imagem do Windows QEMU de destino.
Emulador de máquina de código aberto QEMU
O QEMU é um emulador e virtualizador de máquina genérico e de código aberto que causa tradução dinâmica. Quando o QEMU é usado como um emulador de máquina; ele pode executar sistemas operacionais e programas desenvolvidos para um processador (como um Arm64) em um computador diferente (um PC x64). Ele também pode executar/hospedar imagens de máquinas virtuais para diferentes sistemas operacionais (Windows/Linux/Mac).
O QEMU pode operar com outros hipervisores como KVM para usar extensões de CPU (HVM) para virtualização. Quando o QEMU é usado como um virtualizador, o QEMU atinge desempenhos quase nativos executando o código do convidado diretamente na CPU do host. O QEMU pode aproveitar os recursos do hipervisor do sistema operacional para descarregar a emulação de CPU e MMU para hardware real.
Baixe e instale o QEMU
Neste passo a passo, o QEMU para Windows x64 será instalado em um PC x64 em que o depurador do Windows também será executado.
Baixe o QEMU da página de download do QEMU: https://www.qemu.org/download/
Veja a documentação do QEMU para obter informações sobre como instalar o QEMU: https://www.qemu.org/documentation/
Configurar um disco virtual de destino
Localize ou crie uma imagem de disco virtual que tenha o software que você deseja depurar.
Neste exemplo, uma imagem de disco da máquina virtual VHDX x64 Windows será usada. Para saber mais sobre imagens de máquina virtual do Windows, confira Criar máquina virtual com Hyper-V no Windows 10.
Injetar os drivers VirtIO na imagem do Windows
Para permitir a funcionalidade de rede e o desempenho aceitável do dispositivo de armazenamento, injete ou instale os drivers VirtIO na imagem de disco da máquina virtual do Windows. Os drivers VirtIO estão disponíveis aqui: https://github.com/virtio-win/kvm-guest-drivers-windows
VirtIO é uma interface padronizada que permite o acesso de máquinas virtuais a hardware abstraído, como dispositivos de bloco, adaptadores de rede e consoles. O VirtIO serve como uma camada de abstração para dispositivos de hardware em um ambiente virtualizado como o QEMU.
Para injetar o driver VirtIO na imagem do Windows, siga as etapas abaixo:
- Extraia os drivers VirtIo em uma pasta, por exemplo
C:\VirtIo_Drivers
. - Monte o VHDX que contém a máquina virtual Windows x64 clicando duas vezes no VHDX no Explorador de Arquivos (você também pode usar diskpart). O Windows montará o VHDX usando uma letra específica, por exemplo, "L:"
- Injete o driver na imagem montada usando o Dism:
dism /image:L: /Add-Driver /driver:C:\VirtIo_Drivers
para obter mais informações sobre o DISM, consulte Visão geral do DISM. - Quando o processo for concluído, você poderá desmontar a imagem e continuar a converter o VHDX em QEMU.
Converter VHDX para QEMU
Esta etapa não é obrigatória, mas é recomendada, pois um melhor desempenho é atingido ao usar uma imagem QCOW do QEMU, em vez de um VHDX.
Use o comando qemu-img.exe a seguir para converter o vhdx. Este utilitário está localizado onde você instalou o QEMU, por exemplo, C:\Program Files\qemu
.
C:\Program Files\qemu> qemu-img convert -c -p -O qcow2 MyVHDXFile.vhdx MyQEMUFile.qcow2
Baixar o firmware UEFI
Para obter os melhores resultados, baixe ou compile o arquivo de firmware UEFI (OVMF.fd). O firmware é necessário porque, caso contrário, o QEMU emula por padrão os sistemas BIOS mais antigos.
Uma fonte para o Firmware UEFI é o projeto Open Clear Linux: https://clearlinux.org/
O arquivo OVMF.fd
UEFI de exemplo está disponível aqui: https://github.com/clearlinux/common/tree/master/OVMF.fd
Extraia o conteúdo do arquivo baixado em C:\Program Files\qemu\Firmware
.
Para plataformas diferentes de Intel AMD64, você deve compilar o firmware do EDK2. Para obter mais informações, consulte https://github.com/tianocore/tianocore.github.io/wiki/How-to-build-OVMF.
Configurar script de inicialização do QEMU
Crie seu arquivo de configuração no QEMU. Por exemplo, crie um StartQEMUx64Windows.bat
arquivo no diretório raiz do QEMU. Veja o arquivo de exemplo abaixo.
Usar o script de inicialização do QEMU para iniciar o QEMU
Execute o script de inicialização do QEMU para iniciar o QEMU.
c:\Program Files\qemu\StartQEMUx64Windows.bat
Se um prompt de defensor de firewall for exibido, conceda ao aplicativo todos os direitos a todos os tipos de redes para habilitar o Windbg por meio do firewall do Windows para o computador do depurador host.
Depois que a Máquina Virtual do Windows for iniciada no ambiente QEMU, a interface do usuário do QEMU será exibida.
Use CTRL+ALT+ uma combinação de teclas numéricas para ir ao console do monitor QEMU. Esse monitor também está disponível usando View->compatmonitor.
Digite gdbserver
para iniciar o servidor GDB front-end no QEMU.
O QEMU deve exibir Waiting for gdb connection on device ‘tcp::1234’
.
Retorne à janela principal usando a combinação de teclas CTRL+ALT+1.
Dica: A janela do console GDB suporta o system_reset
comando para reiniciar rapidamente a emulação. Digite help
para obter uma lista de comandos do console do GDB.
Exemplo de script de inicialização da VM do Windows x64 do QEMU
Aqui está um exemplo de script de configuração do QEMU que pode ser usado para Máquinas Virtuais AMD64. Substitua os links que apontam para os arquivos DISK e CD-ROM para os locais no seu PC.
REM
REM This script is used to run a Windows x64 VM on QEMU that is hosted by a Windows x64 host system
REM The Host system is a PC with Intel(R) Xeon(R) CPU.
REM
set EXECUTABLE=qemu-system-x86_64
set MACHINE=-m 6G -smp 4
REM No acceleration
REM generic cpu emulation.
REM to find out which CPU types are supported by the QEMU version on your system, then run:
REM qemu-system-x86_64.exe -cpu help
REM the see if your host system CPU is listed
REM
set CPU=-machine q35
REM Enables x64 UEFI-BIOS that will be used by QEMU :
set BIOS=-bios "C:\Program Files\qemu\Firmware\OVMF.fd"
REM Use regular GFX simulation
set GFX=-device ramfb -device VGA
set USB_CTRL=-device usb-ehci,id=usbctrl
set KEYB_MOUSE=-device usb-kbd -device usb-tablet
REM # The following line enable the full-speed HD controller (requires separate driver)
REM # Following line uses the AHCI controller for the Virtual Hard Disk:
set DRIVE0=-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0
REM
REM This will set the Windows VM x64 disk image that will be launched by QEMU
REM The disk image is in the qcow2 format accepted by QEMU.
REM You get the .qcow2 image, once you get the VHDX Windows VM x64 image
REM and apply the script to inject the virtio x64 drivers and then run the
REM the QEMU tool to convert the .VHDX image to .qcow2 format
REM i.e.
REM qemu-img convert -c -p -O qcow2 Windows_VM_VHDX_with_injected_drivers_file.vhdx file.qcow2
REM file : points to the specified qcow2 image path.
REM
set DISK0=-drive id=disk,file="C:\Program Files\qemu\MyQEMUFile.qcow2",if=none
REM
REM for kdnet on, then best option:
REM NETWORK0="-netdev user,id=net0,hostfwd=tcp::53389-:3389,hostfwd=tcp::50001-:50001 -device virtio-net,netdev=net0,disable-legacy=on"
REM
REM Create a mapping for the RDP service from port 3389 to 3589.
REM
set NETHOST=-netdev user,id=net0,hostfwd=tcp::3589-:3389
set NETGUEST=-device e1000,netdev=net0
REM # The following line should enable the Daemon (instead of interactive)
set DAEMON=-daemonize"
%EXECUTABLE% %MACHINE% %CPU% %BIOS% %GFX% %USB_CTRL% %DRIVE0% %DISK0% %NETHOST% %NETGUEST%
Conectividade de rede
Host local
Se o servidor GDB foi iniciado corretamente, você verá o número da porta onde o servidor GDB estará escutando e precisará usar essa porta para configurar o par do depurador IP:Port
de host.
Se o depurador de host estiver localizado no mesmo computador que hospeda o convidado QEMU, o identificador Localhost será usado no par IP:Port. Neste exemplo, com o servidor e o depurador de host no mesmo PC, LocalHost:1234
será usado.
Host remoto
Se estiver trabalhando em um computador remoto, localize o endereço IP do Windows (se a sessão do host do depurador não estiver localizada no mesmo computador Windows que a VM QEMU).
O IP <address>
QEMU de destino :<port number>
será configurado na interface do usuário EXDI.
Os comandos a seguir podem ser emitidos no console QEMU (compatmonitor0) para exibir informações sobre o status da rede e da conexão.
info network
info usernet
Para obter informações adicionais sobre o sistema de rede QEMU, confira https://wiki.qemu.org/Documentation/Networking
Baixar e instalar as ferramentas de depuração do Windows no sistema host
Instale as Ferramentas de Depuração do Windows no sistema host. Para obter informações sobre como baixar e instalar as ferramentas do depurador, consulte Ferramentas de depuração para Windows.
Iniciar o WinDbg no sistema host
No cenário descrito aqui, defina as seguintes opções na interface do usuário EXDI para se conectar.
Tipo de destino - QEMU
Arquitetura de destino – x64
Sistema operacional de destino - Windows
Tamanho heurístico de digitalização de imagens - 0xFFE - NT
Servidor Gdb e porta - LocalHost:1234
Quebra de conexões - sim
Embora o uso da interface do usuário EXDI seja recomendado, também é possível iniciar o WinDbg usando a opção de linha de comando semelhante ao que é mostrado aqui.
c:\Debuggers> windbg.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,Inproc=ExdiGdbSrv.dll,DataBreaks=Exdi
Ao usar a linha de comando, o endereço IP e a porta são configurados usando o arquivo exdiConfigData.xml. Para obter mais informações, consulte Arquivos de configuração XML EXDI.
Para exibir a saída adicional, é possível usar a sessão detalhada -v:. Para obter informações gerais sobre as opções do WinDbg, confira Opções de linha de comando do WinDbg.
O depurador deve iniciar e conectar ao GdbServer do QEMU.
O depurador mostrará a inicialização de transporte da EXDI com êxito.
EXDI: DbgCoInitialize returned 0x00000001
EXDI: CoCreateInstance() returned 0x00000000
EXDI: QueryInterface(IExdiServer3) returned 0x00000000
Target command response: QEMU
exdiCmd: The function: 'ExdiDbgType' was completed.
EXDI: Server::GetTargetInfo() returned 0x00000000
EXDI: Server::SetKeepaliveInterface() returned 0x00000000
EXDI: Server::GetNbCodeBpAvail() returned 0x00000000
EXDI: ExdiNotifyRunChange::Initialize() returned 0x00000000
EXDI: LiveKernelTargetInfo::Initialize() returned 0x00000000
EXDI: Target initialization succeeded
A janela de pacotes do console EXDIGdbServer também pode exibir informações sobre o status da conexão EXDI, se *"Mostrar log de pacotes de comunicação em Opções avançadas estiver definido como ativado. Para obter mais informações, veja as informações de solução de problemas em Configurar o transporte do depurador EXDI.
Usar o WinDbg para depurar a imagem do Windows QEMU de destino
O dbgeng.dll usa um algoritmo heurístico para encontrar o local do endereço de carga base do NT no momento em que ocorreu o comando de interrupção. Se os símbolos privados não estiverem disponíveis, esse processo falhará.
Isso significa que, em muitas sequências de conexão, a interrupção não funcionará conforme o esperado. Se você interromper manualmente o código, será um local aleatório que o Windows estava executando naquele momento. Como os símbolos para o código de destino podem não estar disponíveis, pode ser difícil definir pontos de interrupção usando símbolos.
Comandos de acesso à memória do depurador disponíveis
Como os seguintes comandos que acessam a memória diretamente funcionarão.
k, kb, kc, kd, kp, kP, kv (Exibir Backtrace da Pilha)
d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory)
E você pode passar pelo código.
Há também comandos que podem ser usados para tentar localizar o código que você deseja depurar.
.imgscan (Localizar cabeçalhos de imagem)
Imgscan pode ser útil com a depuração EDXI, pois ao contrário da depuração de kernel baseada em KDNET tradicional, a definição de pontos de interrupção com base em símbolos pode não estar disponível. Localizar uma imagem de destino desejada pode facilitar o uso de sua localização para definir um ponto de interrupção de acesso à memória.
.exdicmd (Comando EXDI)
O .exdicmd envia um comando EXDI para o sistema de destino usando a conexão de depuração EXDI ativa. Para obter mais informações, confira .exdicmd (Comando EXDI).
Solução de problemas
Veja as informações de solução de problemas em Configurar o transporte do depurador EXDI.
Confira também
Configurar o transporte do depurador EXDI
Arquivos de configuração XML EXDI
Como configurar a depuração automática do kernel de rede KDNET
Como configurar a depuração do kernel de rede KDNET manualmente