Configurazione del debug Kernel-Mode QEMU tramite EXDI

Questo argomento descrive come configurare QEMU Kernel-Mode Debug tramite EXDI. Il debugger Windows supporta il debug del kernel di un ambiente QEMU tramite EXDI. In questo documento vengono descritti i passaggi necessari per stabilire una sessione RSP GdbServer tra il server GDB ExdiGdbSrv.dll (client del server GDB) e il server GDB QEMU.

Lo scenario descritto usa una macchina virtuale Windows x64 e un server GDB QEMU, anche in esecuzione in Windows.

È possibile connettersi ad altri sistemi operativi che fungono da host, ad esempio Linux. QEMU, il software di virtualizzazione e emulazione di macchine, può essere eseguito su numerose architetture, ad esempio x64 e Arm64. Il server di debug di ExdiGdb supporta anche altri processori, ad esempio è possibile usare WinDbg per eseguire il debug di QEMU in esecuzione in Arm64. In questo modo sono disponibili più opzioni, per eseguire il debug di macchine virtuali Windows, in modo che la macchina virtuale Windows possa essere sottoposto a debug tramite il server GDB QEMU disponibile connesso al client del server GDB EXDI Host debugger.

Per informazioni generali sulla configurazione e la risoluzione dei problemi di connessioni EXDI, vedere Configurazione del trasporto del debugger EXDI.

Nota

EXDI è una forma avanzata e specializzata di debug per ambienti specifici. L'uso di una connessione KDNET standard è più semplice da configurare ed è consigliabile. Per configurare automaticamente il debug di rete, vedere Configurazione automatica del debug del kernel di rete KDNET.

EXDI COM Server

EXDI è un'interfaccia che consente di estendere WinDbg aggiungendo il supporto per i debugger hardware (ad esempio, basato su JTAG o basato su GdbServer). Il diagramma seguente illustra il ruolo di EXDI-GdbServer.

Diagramma dello stack che mostra il ruolo di EXDI-GdbServer con WinDbg-DbgEng in alto, un'interfaccia EXDI e un server COM EXDI che comunica con un server GDB.

Importante

Poiché EXDI non usa il protocollo KDNET, il debugger connesso ha meno informazioni su ciò che è in esecuzione nel PC e molti comandi funzioneranno in modo diverso o potrebbero non funzionare affatto. L'accesso ai simboli privati per il codice sottoposto a debug può aiutare il debugger a comprendere meglio l'esecuzione del codice dei sistemi di destinazione. Per altre informazioni, vedere Simboli pubblici e privati.

Configurare una connessione del debugger a un'immagine windows in QEMU

In questo argomento verrà descritto il processo di collegamento a un'immagine di Windows virtuale QEMU in esecuzione in Windows.

  1. Scaricare e installare QEMU in Windows.
  2. Configurare un'immagine di Windows virtuale QEMU di destinazione per l'avvio con le impostazioni di rete e BIOS/UEFI necessarie per il debug.
  3. Avviare l'ambiente QEMU usando lo script di avvio configurato.
  4. Avviare gdbserver in QEMU.
  5. Controllare la connettività di rete e individuare e registrare l'indirizzo IP dell'immagine di destinazione. (Indirizzo IP HOST predefinito 1.2.3.4).
  6. Scaricare e installare gli strumenti di debug di Windows nel sistema host.
  7. Scaricare, compilare, registrare e configurare il server EXDI per QEMU disponibile in GitHub.
  8. Configurare l'host del debugger (WinDbg) modificando i file XML di configurazione EXDI.
  9. Avviare WinDbg usando la riga di comando per connettersi al server EXDI.
  10. Usare WinDbg per eseguire il debug dell'immagine windows QEMU di destinazione.

Scaricare e installare QEMU in Windows

QEMU è un emulatore di macchina generico e open source e un virtualizzatore che causa la conversione dinamica. Quando QEMU viene usato come emulatore di computer, può eseguire i programmi e del sistema operativo creati per un processore (ad esempio Arm64) in un computer diverso (un PC x64). Può anche eseguire/ospitare immagini di macchine virtuali per sistemi operativi diversi (Windows/Linux/Mac).

QEMU può usare altri hypervisor come KVM per usare le estensioni della CPU (HVM) per la virtualizzazione. Quando QEMU viene usato come virtualizzatore, QEMU ottiene prestazioni quasi native eseguendo il codice guest direttamente nella CPU host. QEMU può sfruttare le funzionalità dell'hypervisor del sistema operativo per eseguire l'offload dell'emulazione di CPU e MMU nell'hardware reale.

Scaricare e installare QEMU

In questa procedura dettagliata, QEMU per Windows x64 verrà installato in un PC x64 in cui verrà eseguito anche il debugger di Windows.

Scaricare QEMU dalla pagina di download di QEMU: https://www.qemu.org/download/

Per informazioni sull'installazione di QEMU, vedere la documentazione QEMU: https://www.qemu.org/documentation/

Configurare un disco virtuale di destinazione

Individuare o creare un'immagine del disco virtuale con il software di cui si vuole eseguire il debug.

In questo esempio verrà usata un'immagine disco della macchina virtuale VHDX x64 di Windows. Per altre informazioni sulle immagini delle macchine virtuali Windows, vedere Creare una macchina virtuale con Hyper-V in Windows 10.

Inserire i driver VirtIO nell'immagine di Windows

Per consentire funzionalità di rete e prestazioni ragionevoli dei dispositivi di archiviazione, inserire o installare i driver VirtIO nell'immagine del disco della macchina virtuale Windows. I driver VirtIo sono disponibili qui: https://github.com/virtio-win/kvm-guest-drivers-windows

VirtIO è un'interfaccia standardizzata che consente alle macchine virtuali di accedere a hardware astratto, ad esempio dispositivi a blocchi, schede di rete e console. Virtio funge da livello di astrazione per i dispositivi hardware in un ambiente virtualizzato come QEMU.

Convertire VHDX in QEMU

Questo passaggio non è obbligatorio, ma è consigliabile, poiché si ottengono prestazioni migliori quando si usa un'immagine QEMU QCOW nativa anziché un VHDX.

Usare il comando qemu-img.exe seguente per convertire il file vhdx. Questa utilità si trova in cui è stato installato QEMU, ad esempio C:\Program Files\qemu.

C:\Program Files\qemu> qemu-img convert -c -p -O qcow2 MyVHDXFile.vhdx MyQEMUFile.qcow2 

Scaricare il firmware UEFI

Per ottenere risultati ottimali, scaricare o compilare il file del firmware UEFI (OVMF.fd). Il firmware è necessario perché per impostazione predefinita QEMU emula i sistemi BIOS meno recenti.

Un'origine per il firmware UEFI è il progetto Open Clear Linux: https://clearlinux.org/

Il file UEFI OVMF.fd di esempio è disponibile qui: https://github.com/clearlinux/common/blob/master/OVMF.fd

Estrarre il contenuto del file scaricato in C:\Program Files\qemu\Firmware.

Per le piattaforme diverse da Intel AMD64 è necessario compilare il firmware da EDK2. Per altre informazioni, vedere https://github.com/tianocore/tianocore.github.io/wiki/How-to-build-OVMF.

Configurare lo script di avvio QEMU

Creare il file di configurazione in QEMU. Ad esempio, creare un StartQEMUx64Windows.bat file nella directory radice QEMU. Vedere il file di esempio seguente.

Usare lo script di avvio QEMU per avviare QEMU

Eseguire lo script di avvio QEMU per avviare QEMU.

c:\Program Files\qemu\StartQEMUx64Windows.bat

Se viene visualizzata una richiesta di Firewall Defender, concedere all'app tutti i diritti a tutti i tipi di reti per abilitare Windbg tramite Windows Firewall per il computer del debugger host.

Windows Defender finestra di dialogo Firewall con tutte e tre le opzioni selezionate.

Dopo l'avvio della macchina virtuale Windows nell'ambiente QEMU, verrà visualizzata l'interfaccia utente QEMU.

Screenshot di QEMU che mostra le opzioni del menu di visualizzazione.

Usare CTRL+ALT+ una combinazione di tasti numerici per passare alla console di monitoraggio QEMU. Questo monitoraggio è disponibile anche tramite View-compatmonitor>.

Digitare gdbserver per avviare il server GDB front-end in QEMU.

QEMU dovrebbe essere visualizzato Waiting for gdb connection on device ‘tcp::1234’

Tornare alla finestra principale usando la combinazione di tasti CTRL+ALT+1.

Suggerimento: la finestra della console GDB supporta il comando "system_reset" per riavviare rapidamente l'emulazione. Digitare la Guida per un elenco di comandi della console GDB.

Esempio di script di avvio di macchine virtuali Windows QEMU x64

Di seguito è riportato un esempio di script di configurazione QEMU che può essere usato per Macchine virtuali AMD64. Sostituire i collegamenti che puntano ai file DISK e CDROM nei percorsi del 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 D:\temp\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=D:\temp\x64_image_qcow2_for_windows\basex64Client.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
    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 DEAMON=-daemonize"
    %EXECUTABLE% %MACHINE% %CPU% %BIOS% %GFX% %USB_CTRL% %DRIVE0% %DISK0% %NETHOST% %NETGUEST%

Verificare la connettività della rete

Assicurarsi di ottenere l'indirizzo IP di Windows (se la sessione host del debugger non si trova nello stesso computer Windows della macchina virtuale QEMU).

Se il server GDB è stato avviato correttamente, verrà visualizzato il numero di porta in cui sarà in ascolto il server GDB e sarà necessario usare questa porta per configurare il debugger host (coppia IP:Porta) nel exdiConfigData.xml.

Se il debugger host si trova nello stesso computer che ospita il guest QEMU, l'identificatore Localhost verrà usato nella exdiconfigdata.xml come coppia IP:Port (ad esempio LocalHost:Port:1234). In questo esempio, con il server e il debugger host nello stesso PC, verranno usati i valori predefiniti.

Impostare il valore corrente dell'attributo del nome di destinazione (CurrentTarget) su "QEMU" nel file ExdiConfigData.xml.

Se si usa un PC remoto, impostare l'indirizzo IP <address> QEMU di destinazione: porta <number> in cui il server GDB è in ascolto:

  • Individuare l'elemento Tag del componente QEMU nel exdiCondifgData.xml.
  • Impostare il numero IP:Porta (LocalHost se debugger viene eseguito nello stesso host della macchina virtuale QEMU) per il server GDB QEMU in base a:
  • Salvare le modifiche apportate al file exdiConfigdata.xml che si trova nel percorso specificato da EXDI_GDBSRV_XML_CONFIG_FILE variabile di ambiente.

Per altre informazioni sulla rete QEMU, vedere https://wiki.qemu.org/Documentation/Networking

I comandi seguenti possono essere emessi nella console QEMU (compatmonitor0) per visualizzare informazioni sullo stato della rete e della connessione.

info network
info usernet

Scaricare e installare gli strumenti di debug di Windows nel sistema host

Installare gli strumenti di debug di Windows nel sistema host. Per informazioni sul download e l'installazione degli strumenti del debugger, vedere Debug degli strumenti per Windows.

Scaricare, compilare e registrare la DLL del server EXDI

Scaricare il codice sorgente ExdiGdbSrv.dll binario (client del server COM EXDI) dal codice sorgente microsoft/WinDbg-Samples, GitHub https://github.com/microsoft/WinDbg-Samples)

git clone https://github.com/microsoft/WinDbg-Samples

Creare la soluzione VS (ExdiGdbSrv.sln) in base all'architettura dell'installazione del debugger host situata in Exdi/exdigdbsrv.

Individuare la ExdiGdbSrv.dll prodotta dalla compilazione.

Copiare il server com EXDI (ExdiGdbSrv.dll) nel computer Host nella directory contenente il debugger, .g. C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 o C:\Debuggers)

Usare regsvr32 per registrare la DLL in un prompt dei comandi amministratore.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>regsvr32 ExdiGdbSrv.dll

RegSvr32 deve restituire un messaggio che indica che .DLLRegisterServer in ExdiGdbSrv.dll succeeded

Questo passaggio deve essere eseguito una sola volta, ma se si modifica la posizione del ExdiGdbSrv.dll, sarà necessario registrare di nuovo il server COM.

Un'altra opzione consiste nell'usare lo script di PowerShell di esempio per installare la DLL EXDI e avviare il debugger la prima volta. Per altre informazioni, vedere Esempio di script di PowerShell EXDI in Configurazione del trasporto debugger EXDI.

Configurare l'host del debugger (WinDbg) modificando i file XML di configurazione EXDI

Individuare i due file di configurazione necessari in e copiarli in WinDbg-Samples/Exdi/exdigdbsrv/ un computer del debugger host in cui è installato il debugger.

  • exdiConfigData.xml
  • systemregisters.xml

EXDI_GDBSRV_XML_CONFIG_FILE : descrive il percorso completo del file di configurazione xml EXDI.

EXDI_SYSTEM_REGISTERS_MAP_XML_FILE : descrive il percorso completo del file di mappa del registro del sistema XML EXDI.

Per informazioni generali sulla configurazione e la risoluzione dei problemi di connessioni EXDI, nonché sui tag e sugli attributi exdiConfigData.xml, vedere Configurazione del trasporto debugger EXDI.

Impostare la variabile di ambiente EXDI_GDBSRV_XML_CONFIG_FILE e EXDI_SYSTEM_REGISTERS_MAP_XML_FILE per descrivere il percorso completo del file di configurazione xml exdi.

Prompt dei comandi

Aprire un prompt dei comandi e impostare le variabili di ambiente seguenti.

set EXDI_GDBSRV_XML_CONFIG_FILE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml"

set EXDI_SYSTEM_REGISTERS_MAP_XML_FILE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml"

Digitare SET per verificare che il percorso specificato sia disponibile dalla posizione del ExdiGdbSrvSample.dll

PowerShell

Aprire un prompt di PowerShell e impostare le variabili di ambiente seguenti:

$env:EXDI_GDBSRV_XML_CONFIG_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml'

$env:EXDI_SYSTEM_REGISTERS_MAP_XML_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml'

Digitare dir env: per verificare che il percorso specificato sia disponibile dalla posizione del ExdiGdbSrvSample.dll

Avviare WinDbg nel sistema host

Avviare la sessione windbg tramite l'interfaccia exdi nello stesso prompt dei comandi in cui si impostano le variabili di ambiente (EXDI_GDBSRV_XML_CONFIG_FILE e EXDI_SYSTEM_REGISTERS_MAP_XML_FILE).

c:\Debuggers> windbg.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi

Per visualizzare un output aggiuntivo, è possibile usare la sessione -v: dettagliata. Per informazioni generali sulle opzioni winDbg, vedere Opzioni di Command-Line WinDbg.

Un'altra opzione consiste nell'usare lo script di PowerShell di esempio per installare la DLL EXDI e avviare il debugger la prima volta. Per altre informazioni, vedere Esempio di script di PowerShell EXDI, in Configurazione del trasporto debugger EXDI.

PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

Il debugger deve avviare e connettersi al QEMU GdbServer.

Sessione WinDbg principale che visualizza EXDI CLSID nel titolo della finestra.

Il debugger mostrerà l'inizializzazione del trasporto EXDI riuscita.

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

La finestra pacchetti della console EXDIGdbServer può anche visualizzare informazioni sullo stato della connessione EXDI, se displayCommPackets="sì" è impostato nel file exdiConfigData.xml. Per altre informazioni, vedere le informazioni sulla risoluzione dei problemi in Configurazione del trasporto debugger EXDI.

Usare WinDbg per eseguire il debug dell'immagine di Windows QEMU di destinazione

Il dbgeng.dll usa un algoritmo euristico per trovare la posizione dell'indirizzo di carico di base NT al momento in cui si è verificato il comando di interruzione. Se i simboli privati non sono disponibili, questo processo avrà esito negativo.

Ciò significa che in molte sequenze di connessione l'interruzione non funzionerà come previsto. se si interrompe manualmente il codice, si tratta di una posizione casuale che Windows è stato eseguito in quel momento. Poiché i simboli per il codice di destinazione potrebbero non essere disponibili, è difficile impostare i punti di interruzione usando i simboli.

I comandi come quelli seguenti che accedono direttamente alla memoria funzioneranno.

k, kb, kc, kd, kp, kP, kv (Display Stack Backtrace)

r (Registri)

d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory)

u (Unassemble)

È inoltre possibile eseguire il codice.

p (passaggio)

Esistono anche comandi che possono essere usati per tentare di individuare il codice che si desidera eseguire il debug.

s (Memoria di ricerca)

.imgscan (Trova intestazioni immagine)

Imgscan può essere utile con il debug EDXI, come a differenza del debug del kernel basato su KDNET tradizionale, l'impostazione dei punti di interruzione in base ai simboli potrebbe non essere disponibile. L'individuazione di un'immagine di destinazione desiderata può facilitare l'uso della posizione per impostare un punto di interruzione di accesso alla memoria.

.exdicmd (comando EXDI)

L'exdicmd invia un comando EXDI al sistema di destinazione usando la connessione di debug EXDI attiva. Per altre informazioni, vedere .exdicmd (comando EXDI).

File di configurazione XML EXDI

Esistono due file xml necessari usati dal server COM EXDI GDB (ExdiGdbSrv.dll).

  1. exdiConfigData.xml : questo file contiene i dati di configurazione principali richiesti dal client del server GDB per stabilire una sessione GDB con la destinazione del server GDB del debugger HW, quindi il client del server GDB non verrà eseguito se il percorso del file non è impostato dalla variabile di ambiente EXDI_GDBSRV_XML_CONFIG_FILE. Ogni tag xml consente di configurare un set specifico di funzionalità del server GDB. Per un elenco degli attributi che è possibile modificare nel codice XML e nel codice XML di esempio, vedere di seguito.

  2. Systemregister.xml : questo file contiene un mapping tra i registri del sistema e il codice di accesso. Questo è necessario perché il codice di accesso non è fornito dal server GDB nel file xml e il debugger accede a ogni registro di sistema tramite il codice di accesso.

Per altre informazioni e una descrizione dei tag e degli attributi GDBServer definiti nei file di configurazione XML, vedere Configurazione del trasporto debugger EXDI.

Risoluzione dei problemi

Fare riferimento alle informazioni sulla risoluzione dei problemi in Configurazione del trasporto debugger EXDI.

Vedi anche

Configurazione del trasporto debugger EXDI

.exdicmd (comando EXDI)

Configurazione automatica del debug del kernel di rete KDNET

Configurazione manuale del debug del kernel di rete KDNET