Partager via


Configuration du transport du débogueur EXDI

Cette rubrique explique comment configurer le débogage en mode noyau à l’aide d’EXDI. L’interface de débogage étendue (EXDI) est une couche d’adaptation entre un débogueur logiciel et une cible de débogage. Les outils de débogage pour Windows prennent en charge le débogage du noyau à l’aide d’EXDI à partir de Windows version 22000.

EXDI peut permettre d’établir une connexion avec l’environnement virtuel QEMU. Pour en savoir plus, consulter Configuration du débogage en mode noyau QEMU à l’aide d’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, consulter la configuration automatique du débogage réseau du noyau KDNET.

Présentation du 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.

La connexion EXDI ne dépend pas de Windows ou du protocole KDNET chargé sur le PC cible. Étant donné que ces composants de débogueur logiciel ne sont pas obligatoires, EXDI peut s'avérer utile au début de l’affichage de l’appareil et dans le débogage des problèmes de démarrage du système d’exploitation.

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, consulter Symboles publics et privés.

Configuration requise pour l’appareil EXDI en mode noyau

L’ordinateur qui exécute le débogueur est appelé l’ordinateur hôte, et l’ordinateur en cours de débogage est appelé l’ordinateur cible.

Ce qui suit est nécessaire :

  • Sur les ordinateurs cible et hôte, une carte réseau prise en charge par l'environnement souhaité, tel que QEMU.

  • Une connexion réseau entre la cible et l’hôte à l'aide du protocole TCP/IP.

  • Windows 10 ou Windows 11 version 22000 ou ultérieure.

Limites

  • Le débogage matériel EXDI doit être configuré manuellement à l’aide de fichiers XML et il n’existe aucune interface utilisateur associée dans les débogueurs Windows.

  • Comme décrit ci-dessus, EXDI n’utilisant pas le protocole KDNET, le débogueur connecté dispose de moins d’informations sur le système cible et l’utilisation du débogueur est différent. Sans accès aux symboles privés pour le code cible, de nombreuses commandes qui utilisent des symboles pour comprendre l’état du système cible ne fonctionneront pas. Dans ce cas, il est possible de visualiser le contenu de la mémoire et du registre, et de désassembler le code. Sans symboles privés, il peut s'aérer très difficile et chronophage de déterminer l’emplacement de l’exécution du code ou l’exécution d’autres tâches de débogage courantes.

Client serveur COM GDB

Cette rubrique aborde l’utilisation du client serveur GDB COM EXDI (ExdiGdbSrv.dll), qui implémente l’interface du débogueur COM EXDI. On peut utiliser la même interface COM pour implémenter d’autres interfaces, notamment un serveur COM EXDI pour JTAG-DCI.

Débogage EXDI et KDNET simultanés

Dans certains scénarios complexes, par exemple dans l’affichage précoce de l’appareil, il peut être utile de disposer de deux connexions à l’appareil cible. Une EXDI et une KDNET. Si la cible est un système d’exploitation Windows, le débogage de logiciels KDNET est configuré comme il le serait normalement, par exemple pour se connecter à une machine virtuelle. Dans cette configuration, l’un des deux débogueurs simultanés peut s’introduire pour déboguer le code sur l’ordinateur cible.

Résumé du processus de configuration d’une connexion EXDI

Cette rubrique décrit le processus de configuration d’une connexion EXDI. Pour obtenir un exemple de scénario d’utilisation d'EXDI, consulter Configuration du débogage en mode noyau QEMU à l’aide d’EXDI.

  1. Télécharger et installer les outils de débogage Windows sur le système hôte.
  2. Télécharger, créer et inscrire la DLL du serveur EXDI.
  3. Configurer la connexion en modifiant les fichiers XML de configuration d'EXDI.
  4. Lancer WinDbg à l’aide de l'option -kx pour se connecter au serveur EXDI.
  5. Utiliser WinDbg pour déboguer le système cible.

Télécharger et installer les outils de débogage Windows

Installer 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écharger, créer et inscrire 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, consulter Exemple de script PowerShell EXDI.

Configurer WinDbg à l’aide des fichiers XML de configuration d'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 en savoir plus sur les balises et les attributs exdiConfigData.xml, consulter les fichiers de configuration XML EXDI ci-dessous.

Dans notre scénario, nous allons définir la valeur suivante sur zéro pour empêcher le débogueur de tenter de localiser le nt !kdVersionBlock.

heuristicScanSize = "0"

Définir les valeurs de chemin d’accès EXDI pour référencer l’emplacement des fichiers de configuration XML

Définir 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. Vérifier que la valeur d’environnement de chemin spécifiée est disponible à partir de l’emplacement de la ExdiGdbSrv.dll.

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'

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

Lancer WinDbg et se connecter au serveur EXDI

Lancer la session windbg via l’interface exdi à la même invite de commandes où l'on a 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=NtBaseAddr,DataBreaks=Exdi

Pour afficher une sortie supplémentaire utile à des fins de diagnostic, on peut utiliser la session -v: détaillée. Pour des informations générales sur les options WinDbg, consulter Options de ligne de commande WinDbg. Pour en savoir plus, consulter les paramètres de chargement d’EXDI WinDbg ci-dessous.

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

EXDI: DbgCoInitialize returned 0x00000001
EXDI: CoCreateInstance() returned 0x00000000
EXDI: QueryInterface(IExdiServer3) returned 0x00000000
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
Kernel Debugger connection established

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

La fenêtre de console EXDIGdbServer peut également afficher des informations sur l’état de la connexion EXDI. Pour en savoir plus sur la console, consulter Résolution des problèmes.

Paramètres de chargement EXDI WinDbg

Les paramètres suivants sont utilisés avec WinDbg pour démarrer une session de noyau EXDI.

-kx: EXDI :Options

Les options EXDI suivantes sont disponibles via l'option -kx.

Paramètre Description
CLSID ID de classe affecté au LiveExdiGdbSrvServer (tel que défini dans le fichier ExdiGdbSrv.idl).
Kd=NtBaseAddr Le moteur de débogueur recherche l’adresse de base NT.
ForceX86 Force le moteur de débogueur à utiliser l’interface IeXdiX86Context3 pour obtenir/définir le contexte du processeur.
DataBreaks=Exdi Autoriser l’utilisation de points d’arrêt de données.
Inproc Autoriser l’utilisation d’une macro inproc Exdi-Server.

Utiliser WinDbg pour déboguer le système 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)

On peut également parcourir le code à l’aide de p (Étape).

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, consulter .exdicmd (commande EXDI).

Dépannage

Utiliser la sortie de la fenêtre ExdiGdbServer pour surveiller la séquence de connexion.

Fenêtre de texte ExdiGdbServer affichant des nombres hexadécimaux longs.

Problème : erreur : Impossible d’établir une connexion avec gbDServer. Vérifier la chaîne de connexion <hostname/ip>:portnumber

Ce problème peut se produire pour plusieurs raisons :

  • La ExdiGdbSrv.dll ne peut pas se connecter au serveur GDB cible.
  • Le serveur GDB n’est pas encore en cours d’exécution sur la cible.
  • Problèmes de pare-feu : vérifier que les deux adresses IP sont accessibles en utilisant ping, un traceur ou un autre outil pour vérifier que le trafic GDB peut passer à travers le pare-feu.

Problème : impossible de démarrer le débogage du noyau à l’aide d’EXDI.

Ce problème peut se produire pour plusieurs raisons :

  • Une autre instance de la ExdiGdbSrv.dll (hébergée par dllhost.exe) s’exécute sur l’ordinateur du débogueur hôte.
  • Arrêter l’instance supplémentaire du service COM hébergeant la ExdiGdbSrv.dll.
    • Commencer par répertorier les processus, à l’aide d’un utilitaire comme TList sur le PC hôte. La DLLHost qui héberge la ExdiGdbSrv.dll affiche ExdiGdbServer.

      tlist 261928 dllhost.exe ExdiGdbServer

    • Utiliser kill -f XXXXX à l’invite de commande du débogueur pour arrêter le processus à l’aide du numéro de processus.

Problème : erreur : impossible de configurer la session GdbServer.

Ce problème peut se produire pour plusieurs raisons :

  • Une erreur s’est produite lors de la localisation des informations de session, telles que le chemin d’accès aux fichiers de configuration XML.

Problème : erreur : la variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE n’est pas définie.

Ce problème peut se produire pour plusieurs raisons :

  • Les variables d'environnement ExdiGdbSrv.dll ne sont pas définies ou ne sont pas disponibles dans l'environnement.

Problème : erreur : la variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE n’est pas définie. L’exemple Exdi-GdbServer ne se poursuit pas à ce stade. Définir le chemin d’accès complet au fichier de configuration Xml Exdi.

Ce problème peut se produire pour plusieurs raisons :

  • La variable d’environnement EXDI_GDBSRV_XML_CONFIG_FILE n’est pas définie. Dans certains cas, ExdiGDbSrv.dll continue à fonctionner en appuyant sur le bouton « OK », mais windbg.exe échoue à interroger les registres système (par exemple, via les fonctions rdmsr/wrmsr).

Problème : le scénario d’erreur avec le système cible n’est pas disponible - DbgCoInitialize a renvoyé 0x00000001

La sortie suivante peut être renvoyée si le système cible n’est pas chargé ou n’est pas disponible.

Microsoft (R) Windows Debugger Version 10.0.20317.1 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

EXDI: DbgCoInitialize returned 0x00000001

Il s’agit d’une erreur courante lorsque le serveur COM ExdiGdbSrv.dll n’a pas pu se connecter à QEMU GDServer, de sorte qu’il peut échouer pour la raison suivante :

  • Échec lors du lancement du serveur COM EXDI (ExdiGDbSrv.dll) via le processus dllhost.exe (associé à COM). Pour résoudre ce problème, redémarrer le PC du débogueur hôte ou se déconnecter de Windows, puis se reconnecter. Si cela ne fonctionne pas, réinscrire le serveur COM EXDI après le redémarrage/la connexion.

    • regsvr32.exe <full path to the ExdiGdbSrv.dll)
  • La session précédente de la ExdiGdbSrv.dll est toujours hébergée par un processus de dllhost.exe. Il faut donc arrêter le processus de dllhost.exe. Vérifier Tlist pour voir le pid de dllhost.exe qui héberge la ExdiGdbSrv.dll et arrêter le pid associé.

  • Le QEMU gdbserver n’a pas encore été lancé ou le fichier exdiconfigdata.xml contient des valeurs IP:Port non valides. Si la session WinDbg est lancée sur le même PC hôte que la machine virtuelle Windows QEMU, l’adresse IP=LocalHost.

Problème : la session de débogage n’a pas pu être lancée : FAILURE HR=0x80004005 :Failed to AttachKernel.

Ce problème peut se produire pour plusieurs raisons :

  • Comme décrit ci-dessus, il est possible que la session précédente de la ExdiGdbSrv.dll soit toujours active. Rechercher et arrêter l’hôte DLL associé, comme décrit ci-dessus.

Boîte de dialogue WinDbg affichant l’échec avec HR 0x80004005.

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. Si le fichier n’est pas défini avec la variable d’environnement EXDI_SYSTEM_REGISTERS_MAP_XML_FILE, la ExdiGdbSrv.dll continue de fonctionner, mais le débogueur ne peut pas accéder à un registre système via des commandes rdmsr ou wrmsr. La liste de ces registres doit être prise en charge par le débogueur matériel du serveur GDB (le nom du registre système spécifique doit être présent dans la liste des registres envoyée dans le fichier xml système).

Balises et attributs GDBServer

Le tableau suivant décrit les balises et attributs GDBServer définis dans le fichier exdiConfigData.xml.

Paramètre Description
ExdiTargets Spécifie quelle configuration cible de serveur GDB spécifique sera utilisée par la ExdiGgbSrv.dll pour établir la connexion GDB avec la cible du serveur GDB, car le fichier exdiConfigData.xml inclut tous les serveurs GDB pris en charge actuellement par la ExdiGdbSrv.dll (ce fichier DOIT être rempli avant d’utiliser la ExdiGdbSrv.dll avec un serveur GDB particulier).
CurrentTarget Spécifie le nom de la cible du serveur GDB (par exemple, cette valeur d’attribut doit correspondre à la valeur de nom de l’une des balises <ExdiTarget Name= incluses par le fichier exdiConfigData.xml.
ExdiTarget il s’agit de la balise de début de toutes les données de configuration incluses par chaque composant cible du serveur GDB.
Nom Spécifie le nom du serveur GDB (par exemple, QEMU, BMC-OpenOCD, Trace32, VMWare).
agentNamePacket Il s’agit du nom du client GDB tel qu’il est reconnu par le débogueur matériel du serveur GDB. Il peut être utilisé par le débogueur matériel du serveur GDB pour se configurer pour des clients GDB spécifiques (par exemple, le serveur Trace32 GDB nécessite que la ExdiGdbSrv.dll envoie le nom « QMS.windbg » pour identifier le client windbg-GDB, puis activer les paquets de mémoire GDB personnalisés uniquement pris en charge pour le client serveur MS GDB (exdiGdbSrv.dll).
ExdiGdbServerConfigData Spécifie les paramètres de configuration associés au composant ExdiGdbSrv.dll.
uuid spécifie l’UUI du composant ExdiGdbSrv.dll.
displayCommPackets Si « oui », nous afficherons les caractères de communication du protocole RSP dans la fenêtre du journal des commandes. Si « non », nous affichons simplement le texte de la paire demande-réponse.
enableThrowExceptionOnMemoryErrors Cet attribut sera vérifié par le client du serveur GDB en cas de paquet de réponse d'erreur GDB (E0x) afin de déterminer si le client doit lever une exception et arrêter la lecture de la mémoire.
qSupportedPacket Il est ainsi possible de configurer le client GDB pour demander quel fichier d’architecture d’inscription xml doit être envoyé par le débogueur matériel du serveur GDB en suivant le fichier de description cible xml (en gros, le client informe le serveur GDB que les architectures sont prises en charge par le client, actuellement, le client prend en charge l’architecture x64).
ExdiGdbServerTargetData Spécifie les paramètres liés à la cible matérielle déboguée par la session GdbServer.
targetArchitecture Chaîne contenant l’architecture matérielle cible. Valeurs possibles : X86, X64, ARM, ARM64. Actuellement, la exdiGdbSrv.dll prend uniquement en charge X86 et ARM.
targetFamily Chaîne contenant la famille de matériel cible. Valeurs possibles : ProcessorFamilyX86, ProcessorFamilyX64, ProcessorFamilyARM, ProcessorFamilyARM64.
numberOfCores Nombre de cœurs de processeur pris en charge par la cible. Ce paramètre est validé lorsque nous utilisons une session multi-Gdbserver (session T32-GdbServer). L’attribut « MultiCoreGdbServerSessions » ci-dessous doit être défini sur « oui ».
EnableSseContext Si « oui », le paquet RSP de contexte « g » inclut des valeurs d’enregistrement à virgule flottante. Ce paramètre est utile uniquement pour les cibles de la famille Intel.
heuristicScanSize configure l'algorithme heuristique rapide du moteur de débogage pour réduire la sonde de mémoire analysée de la taille spécifiée. Si la valeur de l'attribut n'est pas spécifiée (ou « 0 »), le moteur de débogage n'utilisera pas l'algorithme heuristique rapide et reviendra au traditionnel qui analyse la totalité de la mémoire à la recherche de la signature DOS du PE.
targetDescriptionFile spécifie si le serveur GDB envoie un fichier d’en-tête de description cible avant d’envoyer chaque fichier xml distinct. Si ce champ est vide, le client du serveur GDB ne demande pas le registre système de l'architecture xml (par exemple, le serveur GDBs Trace32 qui ne prend pas en charge l'envoi des registres d'architecture dans un fichier xml séparé).
GdbServerConnectionParameters Spécifie les paramètres de session GdbServer. Ces paramètres sont utilisés pour contrôler la session GdbServer RSP entre le composant ExdiGdbSrv.dll et GdbServer.
MultiCoreGdbServerSessions Si « oui », il y aura une session GdbServer multicœur (celle utilisée par le serveur principal T32-GdbServer). Si « non », on communiquera avec une seule instance de GdbServer.
MaximumGdbServerPacketLength Il s’agit de la longueur maximale prise en charge par GdbServer pour un paquet.
MaximumConnectAttempts Il s’agit des tentatives de connexion maximales. La ExdiGdbSrv.dll l'utilise pour tenter d’établir la connexion RSP au GdbServer.
SendPacketTimeout Il s’agit du délai d’attente d’envoi du RSP.
ReceivePacketTimeout Il s’agit du délai d’expiration de réception RSP.
HostNameAndPort Il s'agit de la chaîne de connexion au format <hostname/ip address:Port number>. Il peut y avoir plusieurs chaîne de connexion GdbServer (comme la session GdbServer multicœur T32). Le nombre de chaînes de connexion doit correspondre au nombre de cœurs.
ExdiGdbServerMemoryCommands Spécifie les différentes manières d'émettre les commandes de mémoire GDB, afin d'obtenir les valeurs des registres système ou d'accéder à la mémoire en lecture/écriture à différents niveaux d'exception du processeur (par exemple, BMC-OpenOCD permet d'accéder au registre CP15 via la commande personnalisée « aarch64 mrs nsec/sec <access code> »).
GdbSpecialMemoryCommand si « oui », le serveur GDB prend en charge les commandes mémoire personnalisées (par exemple, le registre système. Cela doit être défini pour le serveur Trace32 GDB).
PhysicalMemory si « oui », le serveur GDB prend en charge les commandes personnalisées pour la lecture de la mémoire physique (définie pour le serveur Trace32 GDB).
SupervisorMemory si « oui », le serveur GDB prend en charge les commandes personnalisées pour la lecture de la mémoire de supervision (définie pour le serveur Trace32 GDB).
SpecialMemoryRegister si « oui », le serveur GDB prend en charge les commandes personnalisées pour la lecture des registres systèmes (définie pour le serveur Trace32 GDB)
SystemRegistersGdbMonitor si « oui », le serveur GDB prend en charge les commandes personnalisées via la commande moniteur GDB (elle est définie pour BMC Open-OCD).
SystemRegisterDecoding si « oui », le client GDB accepte le décodage du code d’accès avant d’envoyer la commande moniteur GDB.
ExdiGdbServerRegisters Spécifie le jeu central de registres d'une architecture spécifique.
Architecture Architecture du processeur du jeu de registres définis.
FeatureNameSupported Il s’agit du nom du groupe de registres système tel qu’il est fourni par le fichier xml de description du registre système. Il faut identifier le groupe xml du registre système qui fait partie du fichier xml tel qu’il est envoyé par le serveur GDB.
SystemRegistersStart Il permet d'identifier le premier registre système (numéro/ordre de registre bas) qui est signalé comme faisant partie du jeu central de registres (par exemple, sur X64, QEMU ne signale pas le jeu de registres du système x64 dans un fichier de description de cible xml séparé, de sorte que les registres système font partie des registres centraux).
SystemRegistersEnd Il permet d’identifier le dernier registre système (numéro/ordre élevé) signalé dans le cadre du jeu central de registres.
Nom Nom du registre.
Ordre Il s’agit d’un nombre qui identifie l’index dans le tableau des registres. Ce nombre sera utilisé par le client GDB et l’ensemble serveur/requête (p<number>”/”q<number>) enregistrent des paquets.
Size Il s’agit de la taille du registre en octets.

Exemple de fichier exdiConfigData.xml

<ExdiTargets CurrentTarget = "QEMU">
<!-- QEMU SW simulator GDB server configuration -->
    <ExdiTargets CurrentTarget="QEMU">
    <!--  QEMU SW simulator GDB server configuration  -->
    <ExdiTarget Name="QEMU">
    <ExdiGdbServerConfigData agentNamePacket="" uuid="72d4aeda-9723-4972-b89a-679ac79810ef" displayCommPackets="yes" debuggerSessionByCore="no" enableThrowExceptionOnMemoryErrors="yes" qSupportedPacket="qSupported:xmlRegisters=aarch64,i386">
    <ExdiGdbServerTargetData targetArchitecture="ARM64" targetFamily="ProcessorFamilyARM64" numberOfCores="1" EnableSseContext="no" heuristicScanSize="0xfffe" targetDescriptionFile="target.xml"/>
    <GdbServerConnectionParameters MultiCoreGdbServerSessions="no" MaximumGdbServerPacketLength="1024" MaximumConnectAttempts="3" SendPacketTimeout="100" ReceivePacketTimeout="3000">
    <Value HostNameAndPort="LocalHost:1234"/>
    </GdbServerConnectionParameters>
    <ExdiGdbServerMemoryCommands GdbSpecialMemoryCommand="no" PhysicalMemory="no" SupervisorMemory="no" HypervisorMemory="no" SpecialMemoryRegister="no" SystemRegistersGdbMonitor="no" SystemRegisterDecoding="no"> </ExdiGdbServerMemoryCommands>
        <ExdiGdbServerRegisters Architecture = "ARM64" FeatureNameSupported = "sys">
            <Entry Name ="X0"  Order = "0" Size = "8" />
            <Entry Name ="X1"  Order = "1" Size = "8" />
            <Entry Name ="X2"  Order = "2" Size = "8" />
            <Entry Name ="X3"  Order = "3" Size = "8" />
            <Entry Name ="X4"  Order = "4" Size = "8" />
            <Entry Name ="X5"  Order = "5" Size = "8" />
            <Entry Name ="X6"  Order = "6" Size = "8" />
            <Entry Name ="X7"  Order = "7" Size = "8" />
            <Entry Name ="X8"  Order = "8" Size = "8" />
            <Entry Name ="X9"  Order = "9" Size = "8" />
            <Entry Name ="X10" Order = "a"  Size = "8" />
            <Entry Name ="X11" Order = "b"  Size = "8" />
            <Entry Name ="X12" Order = "c"  Size = "8" />
            <Entry Name ="X13" Order = "d"  Size = "8" />
            <Entry Name ="X14" Order = "e"  Size = "8" />
            <Entry Name ="X15" Order = "f"  Size = "8" />
            <Entry Name ="X16" Order = "10" Size = "8" />
            <Entry Name ="X17" Order = "11" Size = "8" />
            <Entry Name ="X18" Order = "12" Size = "8" />
            <Entry Name ="X19" Order = "13" Size = "8" />
            <Entry Name ="X20" Order = "14" Size = "8" />
            <Entry Name ="X21" Order = "15" Size = "8" />
            <Entry Name ="X22" Order = "16" Size = "8" />
            <Entry Name ="X23" Order = "17" Size = "8" />
            <Entry Name ="X24" Order = "18" Size = "8" />
            <Entry Name ="X25" Order = "19" Size = "8" />
            <Entry Name ="X26" Order = "1a" Size = "8" />
            <Entry Name ="X27" Order = "1b" Size = "8" />
            <Entry Name ="X28" Order = "1c" Size = "8" />
            <Entry Name ="fp"  Order = "1d" Size = "8" />
            <Entry Name ="lr"  Order = "1e" Size = "8" />
            <Entry Name ="sp"  Order = "1f" Size = "8" />
            <Entry Name ="pc"  Order = "20" Size = "8" />
            <Entry Name ="cpsr" Order = "21" Size = "8" />
            <Entry Name ="V0" Order = "22" Size = "16" />
            <Entry Name ="V1" Order = "23" Size = "16" />
            <Entry Name ="V2" Order = "24" Size = "16" />
            <Entry Name ="V3" Order = "25" Size = "16" />
            <Entry Name ="V4" Order = "26" Size = "16" />
            <Entry Name ="V5" Order = "27" Size = "16" />
            <Entry Name ="V6" Order = "28" Size = "16" />
            <Entry Name ="V7" Order = "29" Size = "16" />
            <Entry Name ="V8" Order = "2a" Size = "16" />
            <Entry Name ="V9" Order = "2b" Size = "16" />
            <Entry Name ="V10" Order = "2c" Size = "16" />
            <Entry Name ="V11" Order = "2d" Size = "16" />
            <Entry Name ="V12" Order = "2e" Size = "16" />
            <Entry Name ="V13" Order = "2f" Size = "16" />
            <Entry Name ="V14" Order = "30" Size = "16" />
            <Entry Name ="V15" Order = "31" Size = "16" />
            <Entry Name ="V16" Order = "32" Size = "16" />
            <Entry Name ="V17" Order = "33" Size = "16" />
            <Entry Name ="V18" Order = "34" Size = "16" />
            <Entry Name ="V19" Order = "35" Size = "16" />
            <Entry Name ="V20" Order = "36" Size = "16" />
            <Entry Name ="V21" Order = "37" Size = "16" />
            <Entry Name ="V22" Order = "38" Size = "16" />
            <Entry Name ="V23" Order = "39" Size = "16" />
            <Entry Name ="V24" Order = "3a" Size = "16" />
            <Entry Name ="V25" Order = "3b" Size = "16" />
            <Entry Name ="V26" Order = "3c" Size = "16" />
            <Entry Name ="V27" Order = "3d" Size = "16" />
            <Entry Name ="V28" Order = "3e" Size = "16" />
            <Entry Name ="V29" Order = "3f" Size = "16" />
            <Entry Name ="V30" Order = "3f" Size = "16" />
            <Entry Name ="V31" Order = "3f" Size = "16" />
            <Entry Name ="fpsr" Order = "40" Size = "4" />
            <Entry Name ="fpcr" Order = "41" Size = "4" />
        </ExdiGdbServerRegisters>


        <!-- x64 GDB server core resgisters -->
        <ExdiGdbServerRegisters Architecture = "X64" FeatureNameSupported = "sys" SystemRegistersStart = "18" SystemRegistersEnd = "20" >
            <Entry Name ="rax" Order = "0" Size ="8" />
            <Entry Name ="rbx" Order = "1" Size ="8" />
            <Entry Name ="rcx" Order = "2" Size ="8" />
            <Entry Name ="rdx" Order = "3" Size ="8" />
            <Entry Name ="rsi" Order = "4" Size ="8" />
            <Entry Name ="rdi" Order = "5" Size ="8" />
            <Entry Name ="rbp" Order = "6" Size ="8" />
            <Entry Name ="rsp" Order = "7" Size ="8" />
            <Entry Name ="r8"  Order = "8" Size ="8" />
            <Entry Name ="r9"  Order = "9" Size ="8" />
            <Entry Name ="r10" Order = "a" Size ="8" />
            <Entry Name ="r11" Order = "b" Size ="8" />
            <Entry Name ="r12" Order = "c" Size ="8" />
            <Entry Name ="r13" Order = "d" Size ="8" />
            <Entry Name ="r14" Order = "e" Size ="8" />
            <Entry Name ="r15" Order = "f" Size ="8" />
            <Entry Name ="rip" Order = "10" Size ="8" />
            <!-- <flags id="x64_eflags" size="4">
                <field name="" start="22" end="31"/>
                <field name="ID" start="21" end="21"/>
                <field name="VIP" start="20" end="20"/>
                <field name="VIF" start="19" end="19"/>
                <field name="AC" start="18" end="18"/>
                <field name="VM" start="17" end="17"/>
                <field name="RF" start="16" end="16"/>
                <field name="" start="15" end="15"/>
                <field name="NT" start="14" end="14"/>
                <field name="IOPL" start="12" end="13"/>
                <field name="OF" start="11" end="11"/>
                <field name="DF" start="10" end="10"/>
                <field name="IF" start="9" end="9"/>
                <field name="TF" start="8" end="8"/>
                <field name="SF" start="7" end="7"/>
                <field name="ZF" start="6" end="6"/>
                <field name="" start="5" end="5"/>
                <field name="AF" start="4" end="4"/>
                <field name="" start="3" end="3"/>
                <field name="PF" start="2" end="2"/>
                <field name="" start="1" end="1"/>
                <field name="CF" start="0" end="0"/>
            </flags> -->
            <Entry Name ="eflags" Order = "11" Size ="4" />

            <!-- Segment registers -->
            <Entry Name ="cs" Order = "12" Size ="4" />
            <Entry Name ="ss" Order = "13" Size ="4" />
            <Entry Name ="ds" Order = "14" Size ="4" />
            <Entry Name ="es" Order = "15" Size ="4" />
            <Entry Name ="fs" Order = "16" Size ="4" />
            <Entry Name ="gs" Order = "17" Size ="4" />

            <!-- Segment descriptor caches and TLS base MSRs -->
            <!--Entry Name ="cs_base" Order = "18" Size="8"/
            <Entry Name ="ss_base" Order = "18" Size ="8" />
            <Entry Name ="ds_base" Order = "19" Size ="8" />
            <Entry Name ="es_base" Order = "1a" Size ="8" /> -->
            <Entry Name ="fs_base" Order = "18" Size ="8" />
            <Entry Name ="gs_base" Order = "19" Size ="8" />
            <Entry Name ="k_gs_base" Order = "1a" Size ="8" />

            <!-- Control registers -->
            <!-- the cr0 register format fields:
            <flags id="x64_cr0" size="8">
            <field name="PG" start="31" end="31"/>
            <field name="CD" start="30" end="30"/>
            <field name="NW" start="29" end="29"/>
            <field name="AM" start="18" end="18"/>
            <field name="WP" start="16" end="16"/>
            <field name="NE" start="5" end="5"/>
            <field name="ET" start="4" end="4"/>
            <field name="TS" start="3" end="3"/>
            <field name="EM" start="2" end="2"/>
            <field name="MP" start="1" end="1"/>
            <field name="PE" start="0" end="0"/>
            </flags> -->
            <Entry Name ="cr0" Order = "1b" Size ="8" />
            <Entry Name ="cr2" Order = "1c" Size ="8" />

            <!-- the cr3 register format fields:
            <flags id="x64_cr3" size="8">
                <field name="PDBR" start="12" end="63"/>
                <field name="PCID" start="0" end="11"/>
            </flags> -->
            <Entry Name ="cr3" Order = "1d" Size ="8" />

            <!-- the cr4 register format fields:
            <flags id="x64_cr4" size="8">
                <field name="PKE" start="22" end="22"/>
                <field name="SMAP" start="21" end="21"/>
                <field name="SMEP" start="20" end="20"/>
                <field name="OSXSAVE" start="18" end="18"/>
                <field name="PCIDE" start="17" end="17"/>
                <field name="FSGSBASE" start="16" end="16"/>
                <field name="SMXE" start="14" end="14"/>
                <field name="VMXE" start="13" end="13"/>
                <field name="LA57" start="12" end="12"/>
                <field name="UMIP" start="11" end="11"/>
                <field name="OSXMMEXCPT" start="10" end="10"/>
                <field name="OSFXSR" start="9" end="9"/>
                <field name="PCE" start="8" end="8"/>
                <field name="PGE" start="7" end="7"/>
                <field name="MCE" start="6" end="6"/>
                <field name="PAE" start="5" end="5"/>
                <field name="PSE" start="4" end="4"/>
                <field name="DE" start="3" end="3"/>
                <field name="TSD" start="2" end="2"/>
                <field name="PVI" start="1" end="1"/>
                <field name="VME" start="0" end="0"/>
            </flags> -->
            <Entry Name ="cr4" Order = "1e" Size ="8" />
            <Entry Name ="cr8" Order = "1f" Size ="8" />

            <!-- the efer register format fields:
            <flags id="x64_efer" size="8">
            <field name="TCE" start="15" end="15"/>
            <field name="FFXSR" start="14" end="14"/>
            <field name="LMSLE" start="13" end="13"/>
            <field name="SVME" start="12" end="12"/>
            <field name="NXE" start="11" end="11"/>
            <field name="LMA" start="10" end="10"/>
            <field name="LME" start="8" end="8"/>
            <field name="SCE" start="0" end="0"/>
            </flags> -->
            <Entry Name ="efer" Order = "20" Size ="8"/>

            <!-- x87 FPU -->
            <Entry Name ="st0" Order = "21" Size ="10" />
            <Entry Name ="st1" Order = "22" Size ="10" />
            <Entry Name ="st2" Order = "23" Size ="10" />
            <Entry Name ="st3" Order = "24" Size ="10" />
            <Entry Name ="st4" Order = "25" Size ="10" />
            <Entry Name ="st5" Order = "26" Size ="10" />
            <Entry Name ="st6" Order = "27" Size ="10" />
            <Entry Name ="st7" Order = "28" Size ="10" />
            <Entry Name ="fctrl" Order = "29" Size ="4" />
            <Entry Name ="fstat" Order = "2a" Size ="4" />
            <Entry Name ="ftag"  Order = "2b" Size ="4" />
            <Entry Name ="fiseg" Order = "2c" Size ="4" />
            <Entry Name ="fioff" Order = "2d" Size ="4" />
            <Entry Name ="foseg" Order = "2e" Size ="4" />
            <Entry Name ="fooff" Order = "2f" Size ="4" />
            <Entry Name ="fop" Order = "30" Size ="4" />
            <Entry Name ="xmm0" Order = "31" Size ="16"  />
            <Entry Name ="xmm1" Order = "32" Size ="16"  />
            <Entry Name ="xmm2" Order = "33" Size ="16"  />
            <Entry Name ="xmm3" Order = "34" Size ="16"  />
            <Entry Name ="xmm4" Order = "35" Size ="16"  />
            <Entry Name ="xmm5" Order = "36" Size ="16"  />
            <Entry Name ="xmm6" Order = "37" Size ="16"  />
            <Entry Name ="xmm7" Order = "38" Size ="16"  />
            <Entry Name ="xmm8" Order = "39" Size ="16"  />
            <Entry Name ="xmm9" Order = "3a" Size ="16"  />
            <Entry Name ="xmm10" Order = "3b" Size ="16"  />
            <Entry Name ="xmm11" Order = "3c" Size ="16"  />
            <Entry Name ="xmm12" Order = "3d" Size ="16"  />
            <Entry Name ="xmm13" Order = "3e" Size ="16"  />
            <Entry Name ="xmm14" Order = "3f" Size ="16"  />
            <Entry Name ="xmm15" Order = "40" Size ="16"  />
            
            <!-- the mxcsr register format fields:
            <flags id="x64_mxcsr" size="4">
                <field name="IE" start="0" end="0"/>
                <field name="DE" start="1" end="1"/>
                <field name="ZE" start="2" end="2"/>
                <field name="OE" start="3" end="3"/>
                <field name="UE" start="4" end="4"/>
                <field name="PE" start="5" end="5"/>
                <field name="DAZ" start="6" end="6"/>
                <field name="IM" start="7" end="7"/>
                <field name="DM" start="8" end="8"/>
                <field name="ZM" start="9" end="9"/>
                <field name="OM" start="10" end="10"/>
                <field name="UM" start="11" end="11"/>
                <field name="PM" start="12" end="12"/>
                <field name="FZ" start="15" end="15"/>
            </flags> -->
            <Entry Name ="mxcsr" Order = "41" Size ="4" />

        </ExdiGdbServerRegisters>
    </ExdiGdbServerConfigData>
    </ExdiTarget>
    </ExdiTargets>
</ExdiTargets>

Exemple de script PowerShell EXDI

Cet exemple de script PowerShell installe EXDI, puis lance le débogueur. Le script Start-ExdiDebugger.ps1 installe ExdiGdbSrv.dll si nécessaire, configure les fichiers de paramètres xml, vérifie l'exécution des processus dllhost.exe et lance le débogueur pour se connecter à une cible de débogage matérielle du serveur gdb en cours d’exécution.

Voici un exemple d’appel du script de démarrage.

PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64

On peut également spécifier les fichiers générés si nécessaire.

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

Le script Start-ExdiDebugger.ps1 propose les options de paramètres suivantes.

Paramètre Description
ExdiTarget Type de cible auquel se connecter. Correspond à une section spécifique dans le fichier xml des paramètres
HostName Adresse IP ou nom d’hôte de l’ordinateur hébergeant la session du serveur gdb (par défaut, « LocalHost »)
GdbPort Port sur lequel le serveur gdb écoute.
Architecture Architecture de la cible de débogage matériel (ce paramètre implique également le paramètre ArchitectureFamily dans le fichier de paramètres xml)
ExdiDropPath Emplacement des fichiers ExdiGdbSrv.dll, exdiConfigData.xml et systemregisters.xml. Ils seront uniquement copiés si ExdiGdbSrv.dll n’est pas installé ou est mal installé.
ExtraDebuggerArgs Arguments supplémentaires à transmettre sur la ligne de commande du débogueur
PreNTAppDebugging Modifie la valeur de heuristicScanSize de 0xfffe (la meilleure pour NT) en 0xffe (pour les applications pré-NT)
DontTryDllHostCleanup La vérification des instances en cours d’exécution existantes de la ExdiGdbSrv.dll dans dllhost.exe nécessite une élévation. La fourniture de ce commutateur permet au script de s’exécuter sans élévation (même si le débogueur ne fonctionne pas correctement).

Pour permettre l’affichage des paquets, définir la valeur de displayCommPackets sur oui.

    [pscustomobject]@{ Path = 'displayCommPackets'                                  ; value = "yes" } 
.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

Pour plus d’options de paramètres, consulter les commentaires de code.

<#
.Synopsis
    Installs and launches exdi debugger (automating xml file editing)

.Description
    This script will install ExdiGdbSrv.dll if required, configure the xml settings
    files, check for running dllhost.exe processes, and launch the debugger to connect to
    an already running gdb server hardware debugging target.

.Parameter ExdiTarget
    Type of target to connect to. This corresponds to a specific section in the settings xml file

.Parameter HostName
    IP address or hostname of the computer hosting the gdb server session (defaults to "LocalHost")

.Parameter GdbPort
    Port that the gdb server is listening on.

.Parameter Architecture
    Architecture of the hardware debugging target (this parameter also implies the ArchitectureFamily
    parameter in the xml settings file)

.Parameter ExdiDropPath
    Location of the ExdiGdbSrv.dll, exdiConfigData.xml, and systemregisters.xml files. These will
    only be copied if ExdiGdbSrv.dll is not installed or is installed incorrectly.

.Parameter ExtraDebuggerArgs
    Extra arguments to pass on the debugger command line

.Parameter PreNTAppDebugging
    Changes the value of the heuristicScanSize from 0xfffe (best for NT) to 0xffe (for pre-NT Apps)

.Parameter DontTryDllHostCleanup
    Checking for existing running instances of ExdiGdbSrv.dll in dllhost.exe requires elevation.
    Providing this switch will allow the script to run without elevation (although the debugger may not
    function correctly).

.Example
    >---------------- (first run) ------------<
    .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

.Example
    PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64
#>

[CmdletBinding()]
param
(
    [ValidateSet("QEMU")]
    [string]
    $ExdiTarget = "QEMU",

    [string]
    $HostName = "LocalHost",

    [Parameter(Mandatory=$true)]
    [Int]
    $GdbPort,

    [Parameter(Mandatory=$true)]
    [string]
    [ValidateSet("x86", "x64", "arm64")]
    $Architecture,

    [string]
    $ExdiDropPath,

    [string]
    $DebuggerPath,

    [string[]]
    $ExtraDebuggerArgs = @(),

    [switch]
    $PreNTAppDebugging,

    [switch]
    $DontTryDllHostCleanup
)

$ErrorActionPreference = "Stop"

#region Functions

Function Test-Admin
{
    ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
}

Function Find-PathToWindbgX
{
    $InternalWindbgXPath = "$env:LOCALAPPDATA\DBG\UI\WindbgX.exe"
    $ExternalWindbgXPath = "$env:LOCALAPPDATA\Microsoft\WindowsApps\WinDbgX.exe"

    if (Test-Path $InternalWindbgXPath -PathType Leaf)
    {
        return $InternalWindbgXPath
    }
    elseif (Test-Path $ExternalWindbgXPath -PathType Leaf)
    {
        return $ExternalWindbgXPath
    }
}

Function Test-ParameterValidation
{
    $CommandName = $PSCmdlet.MyInvocation.InvocationName
    $ParameterList = (Get-Command -Name $CommandName).Parameters

    foreach ($Parameter in $ParameterList) {
        Get-Variable -Name $Parameter.Values.Name -ErrorAction SilentlyContinue | Out-String | Write-Verbose
    }

    if (-not $DebuggerPath)
    {
        throw "WindbgX is not installed"
    }
    elseif (-not (Test-Path $DebuggerPath -PathType Leaf))
    {
        throw "DebuggerPath param ($DebuggerPath) does not point to a debugger."
    }

    # Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation
    if (-not $DontTryDllHostCleanup -and
        -not $(Test-Admin))
    {
        throw "Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation. Run with the -DontTryDllHostCleanup parameter to skip this check (debugger session init may fail)."
    }
}

Function Get-ExdiInstallPath
{
    Get-ItemPropertyValue -Path "Registry::HKEY_CLASSES_ROOT\CLSID\{29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014}\InProcServer32" -Name "(default)" -ErrorAction SilentlyContinue
}

Function Test-ExdiServerInstalled
{
    # Check registration of exdi server class
    if ($(Get-ExdiInstallPath) -ne $null -and $(Test-Path "$(Get-ExdiInstallPath)"))
    {
        Write-Verbose "Exdi server is installed. Checking installation..."
        $ExdiInstallDir = [System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath))
        if (-not (Test-Path $ExdiInstallDir))
        {
            Write-Host "Currently Registered exdi server does not exist. Reinstalling..."
            return $false
        }
        elseif (-not ((Test-Path "$ExdiInstallDir\exdiConfigData.xml") -and (Test-Path "$ExdiInstallDir\systemregisters.xml")))
        {
            Write-Host "Currently Registered exdi server does not have required xml settings files. Reinstalling..."
            return $false
        }
        else
        {
            Write-Verbose "Exdi server is insalled correctly. Skipping installation..."
            return $true
        }
    }
    else
    {
        Write-Host "Exdi server is not installed. Installing..."
        return $false
    }
}

Function Install-ExdiServer
{
    [CmdletBinding()]
    param
    (
        [string] $InstallFrom,
        [string] $InstallTo
    )
    
    if (-not $(Test-Admin))
    {
        throw "Script needs to be run as an Admin to install exdi software."
    }

    New-Item -ItemType Directory $InstallTo -ErrorAction SilentlyContinue | Write-Verbose
    Copy-Item -Path "$InstallFrom\ExdiGdbSrv.dll" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    Copy-Item -Path "$InstallFrom\exdiConfigData.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    Copy-Item -Path "$InstallFrom\systemregisters.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    regsvr32 /s "$InstallTo\ExdiGdbSrv.dll"

    if ($(Get-ExdiInstallPath) -eq $null)
    {
        throw "Unable to install exdi server"
    }
}

Function Edit-ExdiConfigFile
{
    [CmdletBinding()]
    param
    (
        [string] $ExdiFilePath,
        [string] $ExdiTargetType,
        [PSCustomObject[]] $XmlSettingPathValueList
    )
    
    # Edit exdiConfigData.xml
    [xml]$exdiConfigXml = Get-Content "$ExdiFilePath"

    # Set current target
    $exdiConfigXml.ExdiTargets.CurrentTarget = $ExdiTarget

    # set HostNameAndPort
    $ExdiTargetXmlNode = $exdiConfigXml.SelectSingleNode("//ExdiTargets/ExdiTarget[@Name='$ExdiTarget']/ExdiGdbServerConfigData")

    foreach ($XmlSettingPathValue in $XmlSettingPathValueList)
    {
        Write-Verbose "Processing $XmlSettingPathValue"
        if ($XmlSettingPathValue.Value -eq $null)
        {
            continue
        }

        $PathParts = $XmlSettingPathValue.Path.Split(".")
        $curNode = $ExdiTargetXmlNode
        if ($PathParts.Count -gt 1)
        {
            foreach ($PathPart in $PathParts[0..($PathParts.Count-2)])
            {
                Write-Verbose $PathPart
                $curNode = $curNode.($PathPart)
            }
        }
        $curNode.($PathParts[-1]) = $XmlSettingPathValue.Value
    }

    $exdiConfigXml.Save("$ExdiFilePath")
}

Function Stop-ExdiContainingDllHosts
{
    $DllHostPids = Get-Process dllhost | ForEach-Object { $_.Id }
    foreach ($DllHostPid in $DllHostPids)
    {
        $DllHostExdiDlls = Get-Process -Id $DllHostPid -Module | Where-Object { $_.FileName -like "*ExdiGdbSrv.dll" }
        if ($DllHostExdiDlls.Count -ne 0)
        {
            Write-Verbose "Killing dllhost.exe with pid $DllHostPid (Contained instance of ExdiGdbSrv.dll)"
            Stop-Process -Id $DllHostPid -Force
        }
    }
}

#endregion

#region Script

# Apply defaults for $DebuggerPath before Parameter validation
if (-not $DebuggerPath)
{
    $DebuggerPath = Find-PathToWindbgX
}

Test-ParameterValidation

# look clean up dllhost.exe early since it can hold a lock on files which
# need to be overwritten
if (-not $DontTryDllHostCleanup)
{
    Stop-ExdiContainingDllHosts
}

if (-not $(Test-ExdiServerInstalled))
{
    if (-not $ExdiDropPath)
    {
        throw "ExdiServer is not installed and -ExdiDropPath is not valid"
    }

    $ExdiInstallDir = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($DebuggerPath))" -ChildPath "exdi"
    Install-ExdiServer -InstallFrom "$ExdiDropPath" -InstallTo "$ExdiInstallDir"
}

$SystemRegistersFilepath = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "systemregisters.xml"
$ExdiConfigFilepath      = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "exdiConfigData.xml"

# Calculate implied parameters
$HeuristicScanSize = if ($PreNTAppDebugging) { "0xffe" } else { "0xfffe" }
$ArchitectureFamily = switch($Architecture)
{
    x64   { "ProcessorFamilyx64" }
    x86   { "ProcessorFamilyx86" }
    arm64 { "ProcessorFamilyARM64" }
}

# Path is evaluated relative to the relevant ExdiTarget's ExdiGdbServerConfigData node in the xml schema
$SettingsToChange = @(
    [pscustomobject]@{ Path = 'GdbServerConnectionParameters.Value.HostNameAndPort' ; Value = "${HostName}:$GdbPort" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetArchitecture'          ; Value = "$Architecture" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetFamily'                ; Value = "$ArchitectureFamily" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.heuristicScanSize'           ; Value = "$HeuristicScanSize" },
    [pscustomobject]@{ Path = 'displayCommPackets'                                  ; value = "no" }
)
Edit-ExdiConfigFile -ExdiFilePath "$ExdiConfigFilepath" -ExdiTargetType "$ExdiTarget" -XmlSettingPathValueList $SettingsToChange

# Set env vars for debugger
[System.Environment]::SetEnvironmentVariable('EXDI_GDBSRV_XML_CONFIG_FILE',"$ExdiConfigFilepath")
[System.Environment]::SetEnvironmentVariable('EXDI_SYSTEM_REGISTERS_MAP_XML_FILE',"$SystemRegistersFilepath")

$DebuggerArgs = @("-v", "-kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi")
Write-Verbose "DebuggerPath = $DebuggerPath"
Start-Process -FilePath "$DebuggerPath" -ArgumentList ($DebuggerArgs + $ExtraDebuggerArgs)

#endregion

Voir aussi

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

.exdicmd (commande EXDI)

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

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

Configuration manuelle du débogage en mode noyau