Partager via


Configuration du débogage en mode noyau de QEMU avec EXDI

Cette rubrique explique comment configurer le débogage en mode noyau de QEMU à l’aide d’EXDI. Le débogueur Windows prend en charge le débogage du noyau dans un environnement QEMU à l’aide d’EXDI. Ce document décrit les étapes nécessaires pour établir une session GdbServer RSP entre le serveur ExdiGdbSrv.dll (client de serveur GDB) et le serveur GDB QEMU.

Le scénario décrit utilise une machine virtuelle Windows x64 et un serveur GDB QEMU, également exécuté sur Windows.

Il est possible de se connecter à d’autres systèmes d’exploitation faisant office d’hôte, tels que Linux. QEMU, le logiciel de virtualisation et d’émulation de machine, peut fonctionner sur de nombreuses architectures, notamment x64 et Arm64. Le serveur de débogage ExdiGdb prend également en charge d’autres processeurs, par exemple, on peut utiliser WinDbg pour déboguer QEMU s’exécutant sur Arm64. On dispose ainsi de plusieurs options pour déboguer des machines virtuelles Windows, pour que la machine virtuelle Windows puisse être déboguée au niveau matériel via le serveur GDB QEMU disponible connecté au client de serveur GDB EXDI hôte du débogueur.

Pour des informations générales sur la configuration et la résolution des problèmes liés aux connexions EXDI, consultez Configuration du transport du débogueur EXDI.

Remarque

EXDI est une forme avancée et spécialisée de débogage pour des environnements spécifiques. Nous recommandons l’utilisation d’une connexion KDNET standard, plus facile à configurer. Pour une configuration automatique du débogage réseau, consultez la configuration automatique du débogage réseau du noyau KDNET.

Serveur EXDI COM

EXDI est une interface qui permet d’étendre WinDbg en ajoutant la prise en charge des débogueurs matériels (par exemple, basé sur JTAG ou GdbServer). Le diagramme ci-dessous illustre le rôle d’EXDI-GdbServer.

Diagramme de pile illustrant le rôle d’EXDI-GdbServer avec WinDbg-DbgEng en haut, une interface EXDI et un serveur COM EXDI communiquant avec un serveur GDB.

Important

EXDI n’utilisant pas le protocole KDNET, le débogueur connecté dispose de beaucoup moins d’informations sur ce qui se passe sur le PC et de nombreuses commandes fonctionneront différemment ou ne fonctionneront pas du tout. L’accès aux symboles privés pour le code en cours de débogage peut permettre au débogueur de mieux comprendre l’exécution du code des systèmes cibles. Pour en savoir plus, consultez Symboles publics et privés.

Configurer une connexion de débogueur à une image Windows sur QEMU

Cette rubrique présente la description du processus d’attachement à une image Windows virtuelle QEMU s’exécutant sur Windows.

  1. Téléchargez et installez QEMU sur Windows.
  2. Configurez une image Windows virtuelle QEMU cible à lancer avec les paramètres BIOS/UEFI requis pour le débogage.
  3. Démarrez l’environnement QEMU à l’aide du script de lancement configuré.
  4. Démarrez le gdbserver sur QEMU.
  5. Vérifiez la connectivité réseau et recherchez et enregistrez l’adresse IP de l’image cible. (Adresse IP hôte par défaut 1.2.3.4).
  6. Téléchargez et installez les outils de débogage Windows sur le système hôte.
  7. Téléchargez, générez, inscrivez et configurez le serveur EXDI pour QEMU situé sur GitHub.
  8. Configurez l’hôte du débogueur (WinDbg) en modifiant les fichiers XML de configuration EXDI.
  9. Lancez WinDbg à l’aide de la ligne de commande pour vous connecter au serveur EXDI.
  10. Utilisez WinDbg pour déboguer l’image Windows QEMU cible.

Téléchargez et installez QEMU sur Windows

QEMU est un émulateur de machine et un virtualiseur générique et open source qui permet une traduction dynamique. Lorsque QEMU est utilisé en tant qu’émulateur de machine, il peut exécuter les programmes et les systèmes d’exploitation créés pour un processeur (comme Arm64) sur un autre ordinateur (un PC x64). Il peut également exécuter/héberger des images de machines virtuelles pour différents systèmes d’exploitation (Windows/Linux/Mac).

QEMU peut utiliser d’autres hyperviseurs comme KVM pour utiliser des extensions de processeur (HVM) pour la virtualisation. Lorsque QEMU est utilisé comme virtualiseur, il permet d’obtenir des performances quasi natives en exécutant le code invité directement sur le processeur hôte. QEMU peut tirer parti des fonctions de l’hyperviseur du système d’exploitation pour décharger l’émulation du processeur et de MMU sur le matériel réel.

Téléchargement et installation de QEMU

Dans cette procédure pas à pas, QEMU pour Windows x64 sera installé sur un PC x64 sur lequel s’exécutera également le débogueur Windows.

Téléchargez QEMU à partir de la page de téléchargement QEMU : https://www.qemu.org/download/

Pour en savoir plus sur l’installation de QEMU, consultez la documentation QEMU : https://www.qemu.org/documentation/

Configurer un disque virtuel cible

Localisez ou créez une image de disque virtuel contenant le logiciel que vous souhaitez déboguer.

Dans cet exemple, nous utilisons une image de disque de machine virtuelle VHDX Windows x64. Pour en savoir plus sur les images de machine virtuelle Windows, consultez Créer une machine virtuelle avec Hyper-V sur Windows 10.

Injecter les pilotes VirtIO dans l’image Windows

Pour assurer la fonctionnalité du réseau et des performances raisonnables des périphériques de stockage, il convient d’injecter ou d’installer les pilotes VirtIO dans l’image disque de la machine virtuelle Windows. Les pilotes VirtIo sont disponibles ici : https://github.com/virtio-win/kvm-guest-drivers-windows

VirtIO est une interface normalisée qui permet aux machines virtuelles d’accéder à du matériel abstrait, tel que des périphériques de bloc, des adaptateurs de réseau et des consoles. Virtio fait office de couche d’abstraction aux périphériques matériels dans un environnement virtualisé comme QEMU.

Convert VHDX to QEMU

Cette étape n’est pas obligatoire, mais elle est recommandée, car ont obtient de meilleures performances en utilisant une image QEMU QCOW native au lieu d’un VHDX.

Utilisez la commande qemu-img.exe suivante pour convertir le vhdx. Cet utilitaire se trouve à l’emplacement où vous avez installé QEMU, par exemple C:\Program Files\qemu.

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

Télécharger le microprogramme UEFI

Pour obtenir des résultats optimaux, téléchargez ou compilez le fichier de microprogramme UEFI (OVMF.fd). Le microprogramme est nécessaire, car QEMU émule par défaut les anciens systèmes BIOS.

Le projet Open Clear Linux est l’une des sources permettant d’obtenir le microprogramme UEFI : https://clearlinux.org/

Le fichier UEFI OVMF.fd d’exemple est disponible ici : https://github.com/clearlinux/common/blob/master/OVMF.fd

Extrayez le contenu du fichier téléchargé dans C:\Program Files\qemu\Firmware.

Pour les plateformes autres qu’Intel AMD64, vous devez compiler le microprogramme à partir de l’EDK2. Pour plus d’informations, consultez https://github.com/tianocore/tianocore.github.io/wiki/How-to-build-OVMF.

Configurer le script de lancement QEMU

Créez votre fichier de configuration dans QEMU. Par exemple, créez un fichier StartQEMUx64Windows.bat sous le répertoire racine QEMU. Consultez le fichier d’exemple ci-dessous.

Utilisez le script de lancement QEMU pour lancer QEMU

Exécutez le script de lancement QEMU pour démarrer QEMU.

c:\Program Files\qemu\StartQEMUx64Windows.bat

Si une invite du pare-feu de Windows Defender s’affiche, accordez à l’application tous les droits sur tous les types de réseaux afin d’activer Windbg à travers le pare-feu Windows pour la machine de débogage hôte.

Boîte de dialogue du pare-feu Windows Defender avec les trois options cochées.

Une fois la machine virtuelle Windows lancée dans l’environnement QEMU, l’interface utilisateur QEMU s’affiche.

Capture d’écran des options de menu affichage QEMU.

Utilisez Ctrl+Alt+ une combinaison de touches numériques pour accéder à la console de surveillance QEMU. Cette surveillance est également possible avec View>-compatmonitor.

Saisissez gdbserver pour lancer le serveur GDB frontal sur QEMU.

QEMU doit afficher Waiting for gdb connection on device ‘tcp::1234’

Revenez à la fenêtre principale à l’aide de la combinaison de touches Ctrl+Alt+1.

Conseil : la fenêtre de la console GDB prend en charge la commande « system_reset » pour redémarrer rapidement l’émulation. Saisissez aide pour obtenir la liste des commandes de la console GDB.

Exemple de script de lancement de machine virtuelle Windows QEMU x64

Voici un exemple de script de configuration QEMU qui peut être utilisé pour les machines virtuelles AMD64. Remplacez les liens qui pointent vers les fichiers DISK et CDROM vers les emplacements de votre 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 DAEMON=-daemonize"
    %EXECUTABLE% %MACHINE% %CPU% %BIOS% %GFX% %USB_CTRL% %DRIVE0% %DISK0% %NETHOST% %NETGUEST%

Vérifiez la connectivité réseau

Veillez à obtenir l’adresse IP Windows (si la session hôte du débogueur ne se trouve pas sur le même ordinateur Windows que la machine virtuelle QEMU).

Si le serveur GDB a démarré correctement, le numéro de port où le serveur GDB sera à l’écoute s’affichera, et vous devrez utiliser ce port pour configurer le débogueur hôte (paire IP:Port) dans le exdiConfigData.xml).

Si votre débogueur hôte se trouve sur la même machine que celle qui héberge l’invité QEMU, on utilise l’identificateur Localhost dans le exdiconfigdata.xml en tant que paire IP:Port (par exemple, LocalHost:Port :1234). Dans cet exemple, avec le serveur et le débogueur hôte sur le même PC, on utilise les valeurs par défaut.

Définissez la valeur de l’attribut du nom de la cible actuelle (CurrentTarget) à « QEMU » dans le fichier ExdiConfigData.xml.

Si vous travaillez sur un PC distant, définissez l’adresse IP <address> : Port <number> QEMU où le serveur GDB est à l’écoute :

  • Recherchez l’élément de balise du composant QEMU dans le fichier exdiCondifgData.xml.
  • Définissez le numéro IP:Port (LocalHost si le débogueur s’exécute sur le même hôte que la machine virtuelle QEMU) pour le serveur GDB QEMU comme suit :
  • Enregistrez les modifications apportées au fichier exdiConfigdata.xml situé sur le chemin d’accès spécifié par la variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE.

Pour en savoir plus sur la mise en réseau QEMU, consultez https://wiki.qemu.org/Documentation/Networking

Les commandes suivantes peuvent être émises sur la console QEMU (compatmonitor0) pour afficher des informations sur le réseau et l’état de connexion.

info network
info usernet

Téléchargez et installez les outils de débogage Windows sur le système hôte

Installez les outils de débogage Windows sur le système hôte. Pour des informations sur le téléchargement et l’installation des outils de débogage, consultez la rubrique Outils de débogage pour Windows.

Téléchargez, créez et inscrivez la DLL du serveur EXDI

Téléchargez le code source ExdiGdbSrv.dll binaire (client serveur EXDI COM) correspondant à partir de microsoft/WinDbg-Samples, GitHub https://github.com/microsoft/WinDbg-Samples)

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

Créez la solution VS (ExdiGdbSrv.sln) en fonction de l’architecture de votre installation du débogueur hôte située dans Exdi/exdigdbsrv.

Recherchez la ExdiGdbSrv.dll produite par la build.

Copiez le serveur com EXDI (ExdiGdbSrv.dll) sur l’ordinateur hôte, dans le répertoire contenant votre débogueur, .g. C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 ou C:\Debuggers)

Utilisez regsvr32 pour inscrire la DLL dans une invite de commandes Administrateur

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

RegSvr32 doit renvoyer un message indiquant que le DLLRegisterServer in ExdiGdbSrv.dll succeeded.

Cette étape ne doit être effectuée qu’une seule fois, mais si vous modifiez l’emplacement de ExdiGdbSrv.dll, vous devrez réinscrire le serveur COM.

Une autre option consiste à utiliser l’exemple de script PowerShell pour installer la DLL EXDI et lancer le débogueur la première fois. Pour en savoir plus, consultez Exemple de script PowerShell EXDI dans Configuration du transport du débogueur EXDI.

Configurez l’hôte du débogueur (WinDbg) en modifiant les fichiers XML de configuration EXDI

Recherchez les deux fichiers de configuration nécessaires dans WinDbg-Samples/Exdi/exdigdbsrv/ et copiez-les dans un emplacement local sur votre ordinateur du débogueur hôte là où le débogueur est installé.

  • exdiConfigData.xml
  • systemregisters.xml

EXDI_GDBSRV_XML_CONFIG_FILE : décrit le chemin d’accès complet au fichier de configuration XML EXDI.

EXDI_SYSTEM_REGISTERS_MAP_XML_FILE : décrit le chemin d’accès complet au fichier de mappage du registre du système EXDI xml.

Pour obtenir des informations générales sur la configuration et la résolution des problèmes de connexions EXDI, ainsi que sur les balises et attributs exdiConfigData.xml, consultez Configuration du transport du débogueur EXDI.

Définissez la variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE et EXDI_SYSTEM_REGISTERS_MAP_XML_FILE pour décrire le chemin complet du fichier de configuration xml exdi.

Invite de commandes

Ouvrez une invite de commande et définissez les variables d’environnement suivantes.

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"

Saisissez SET pour confirmer que le chemin d’accès spécifié est disponible à partir de l’emplacement de ExdiGdbSrvSample.dll

Powershell

Ouvrez une invite PowerShell et définissez les variables d’environnement suivantes :

$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'

Saisissez dir env: pour confirmer que le chemin d’accès spécifié est disponible à partir de l’emplacement de ExdiGdbSrvSample.dll

Lancer WinDbg sur le système hôte

Lancez la session windbg via l’interface exdi à la même invite de commandes où vous avez défini les variables d’environnement (EXDI_GDBSRV_XML_CONFIG_FILE et EXDI_SYSTEM_REGISTERS_MAP_XML_FILE).

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

Pour afficher une sortie supplémentaire, on peut utiliser la session -v: détaillée. Pour des informations générales sur les options WinDbg, consultez Options de ligne de commande WinDbg.

Une autre option consiste à utiliser l’exemple de script PowerShell pour installer la DLL EXDI et lancer le débogueur la première fois. Pour en savoir plus, consultez Exemple de script PowerShell EXDI dans Configuration du transport du débogueur EXDI.

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

Le débogueur doit lancer et se connecter au GdbServer QEMU.

Session WinDbg principale affichant EXDI CLSID dans le titre de la fenêtre.

Le débogueur affiche l’initialisation de transport EXDI réussie.

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 fenêtre des paquets de la console EXDIGdbServer peut également afficher des informations sur l’état de la connexion EXDI, si displayCommPackets="yes" est défini dans le fichier exdiConfigData.xml. Pour en savoir plus, consultez les informations sur la résolution des problèmes dans Configuration du transport du débogueur EXDI.

Utilisez WinDbg pour déboguer l’image Windows QEMU cible

La dbgeng.dll utilise un algorithme heuristique pour rechercher l’emplacement de l’adresse de charge de base NT au moment où la commande d’arrêt s’est produite. Si les symboles privés ne sont pas disponibles, ce processus échoue.

Cela signifie que dans de nombreuses séquences de connexion, l’arrêt ne fonctionnera pas comme prévu. si vous accédez manuellement au code, il s’agira d’un emplacement aléatoire que Windows est en train d’exécuter à ce moment-là. Comme les symboles du code cible peuvent ne pas être disponibles, il peut s’avérer difficile de définir des points d’arrêt à l’aide de symboles.

Les commandes comme celles ci-dessous qui accèdent directement à la mémoire fonctionnent.

k, kb, kc, kd, kp, kP, kv (Afficher l’arborescence des appels de procédure)

r (Registres)

d, da, db, dc, dd, dD, df, dp, dq, du, dw (Afficher la mémoire)

u (Désassembler)

Vous pouvez également parcourir le code.

p (Step)

Il existe également des commandes que l’on peut utiliser pour tenter de localiser le code qu’on souhaite déboguer.

s (Rechercher dans la mémoire)

.imgscan (Rechercher des en-têtes d’image)

Imgscan peut être utile pour le débogage EDXI, car contrairement au débogage traditionnel du noyau basé sur KDNET, il n’est pas toujours possible de définir des points d’arrêt basés sur des symboles. La localisation d’une image cible souhaitée peut permettre d’utiliser son emplacement pour définir un point d’arrêt d’accès à la mémoire.

.exdicmd (commande EXDI)

.exdicmd envoie une commande EXDI au système cible à l’aide de la connexion de débogage EXDI active. Pour en savoir plus, consultez .exdicmd (commande EXDI).

Fichiers de configuration XML EXDI

Il existe deux fichiers xml requis qui sont consommés par le serveur COM GDB EXDI (ExdiGdbSrv.dll).

  1. exdiConfigData.xml : ce fichier contient les données de configuration principales requises par le client serveur GDB pour établir une session GDB réussie avec la cible du serveur GDB du débogueur matériel. Le client du serveur GDB ne s’exécute donc pas si l’emplacement du fichier n’est pas défini par la variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE. Chaque balise xml permet de configurer un ensemble spécifique de fonctionnalités de serveur GDB. Consultez ci-dessous la liste des attributs que vous pouvez modifier dans le code XML et l’exemple de code XML.

  2. Systemregister.xml : ce fichier contient un mappage entre les registres système et leur code d’accès. Il est nécessaire, car le code d’accès n’est pas fourni par le serveur GDB dans le fichier xml, et le débogueur accède à chaque registre système via ledit code d’accès.

Pour de plus amples informations et une description des balises et attributs GDBServer définis dans les fichiers de configuration XML, consultez Configuration du transport du débogueur EXDI.

Dépannage

Reportez-vous aux informations de résolution des problèmes de Configuration du transport du débogueur EXDI.

Voir aussi

Configuration du transport du débogueur EXDI

.exdicmd (commande EXDI)

Configuration automatique du débogage du noyau réseau KDNET

Configuration manuelle du débogage du noyau réseau KDNET