web-dev-qa-db-fra.com

Comment fonctionne un débogueur?

Je me demande comment fonctionne un débogueur? Particulièrement celui qui peut être "attaché" à un exécutable déjà en cours d'exécution. Je comprends que le compilateur traduit le code en langage machine, mais comment le débogueur "sait-il" à quoi il est attaché?

157
ya23

Les détails du fonctionnement d'un débogueur dépendent de ce que vous déboguez et de ce qu'est le système d'exploitation. Pour le débogage natif sous Windows, vous pouvez trouver quelques détails sur MSDN: Win32 Debugging API .

L'utilisateur indique au débogueur à quel processus se connecter, soit par nom, soit par ID de processus. S'il s'agit d'un nom, le débogueur recherchera l'ID de processus et lancera la session de débogage via un appel système; sous Windows, ce serait DebugActiveProcess .

Une fois connecté, le débogueur entrera dans une boucle d'événements comme pour toute interface utilisateur, mais au lieu d'événements provenant du système de fenêtrage, le système d'exploitation générera des événements en fonction de ce qui se passe dans le processus en cours de débogage - par exemple, une exception se produit. Voir WaitForDebugEvent .

Le débogueur est capable de lire et d'écrire la mémoire virtuelle du processus cible, et même d'ajuster ses valeurs de registre via des API fournies par le système d'exploitation. Voir la liste des fonctions de débogage pour Windows.

Le débogueur peut utiliser les informations des fichiers de symboles pour traduire des adresses en noms et emplacements de variables dans le code source. Les informations du fichier de symboles sont un ensemble distinct d'API et ne font pas partie intégrante du système d'exploitation en tant que tel. Sous Windows, cela se fait via le Debug Interface Access SDK .

Si vous déboguez un environnement géré (.NET, Java, etc.), le processus sera généralement similaire, mais les détails sont différents, car l'environnement de la machine virtuelle fournit l'API de débogage plutôt que le système d'exploitation sous-jacent.

90
Rob Walker

Si je comprends bien:

Pour les points d'arrêt logiciels sur x86, le débogueur remplace le premier octet de l'instruction par CC ( int3 ). Cela se fait avec WriteProcessMemory sous Windows. Lorsque le CPU accède à cette instruction et exécute le int3 , le CPU génère une exception de débogage. Le système d'exploitation reçoit cette interruption, se rend compte que le processus est en cours de débogage et informe le processus de débogage que le point d'arrêt a été atteint.

Une fois le point d'arrêt atteint et le processus arrêté, le débogueur consulte sa liste de points d'arrêt et remplace le CC par l'octet qui s'y trouvait à l'origine. Le débogueur définit TF, l'indicateur d'interruption dans EFLAGS (en modifiant le CONTEXT =), et poursuit le processus. L'indicateur d'interruption fait que le CPU génère automatiquement une exception en une seule étape ( INT 1 ) sur l'instruction suivante.

Lorsque le processus en cours de débogage s'arrête la prochaine fois, le débogueur remplace à nouveau le premier octet de l'instruction de point d'arrêt par CC, et le processus se poursuit.

Je ne sais pas si c'est exactement la façon dont il est implémenté par tous les débogueurs, mais j'ai écrit un programme Win32 qui parvient à se déboguer en utilisant ce mécanisme. Complètement inutile, mais pédagogique.

54
Jonathon Reinhart

Sous Linux, le débogage d'un processus commence par l'appel système ptrace (2) . Cet article a un excellent tutoriel sur la façon d'utiliser ptrace pour implémenter quelques constructions de débogage simples.

24
Adam Rosenfield

Si vous utilisez un système d'exploitation Windows, une excellente ressource pour cela serait "Débogage des applications pour Microsoft .NET et Microsoft Windows" par John Robbins:

(ou même l'ancienne édition: "Débogage des applications" )

Le livre a un chapitre sur le fonctionnement d'un débogueur qui comprend du code pour quelques débogueurs simples (mais qui fonctionnent).

Comme je ne connais pas les détails du débogage Unix/Linux, ce truc peut ne pas s'appliquer du tout aux autres systèmes d'exploitation. Mais je suppose que comme introduction à un sujet très complexe, les concepts - sinon les détails et les API - devraient être portés sur la plupart des systèmes d'exploitation.

10
Michael Burr

Une autre source précieuse pour comprendre le débogage est le manuel du processeur Intel (Intel® 64 et IA-32 Architectures Software Developer’s Manual). Dans le volume 3A, chapitre 16, il a présenté la prise en charge matérielle du débogage, comme les exceptions spéciales et les registres de débogage matériel. Voici un extrait de ce chapitre:

Indicateur T (trap), TSS - Génère une exception de débogage (#DB) lorsqu'une tentative est effectuée pour basculer vers une tâche avec l'indicateur T défini dans son TSS.

Je ne sais pas si Windows ou Linux utilise ou non cet indicateur, mais il est très intéressant de lire ce chapitre.

J'espère que cela aide quelqu'un.

3
Jiang

Ma compréhension est que lorsque vous compilez une application ou un fichier DLL, tout ce qu'il compile contient des symboles représentant les fonctions et les variables.

Lorsque vous avez une version de débogage, ces symboles sont beaucoup plus détaillés que lorsqu'il s'agit d'une version de version, permettant ainsi au débogueur de vous donner plus d'informations. Lorsque vous associez le débogueur à un processus, il regarde quelles fonctions sont actuellement accessibles et résout tous les symboles de débogage disponibles à partir d'ici (car il sait à quoi ressemblent les internes du fichier compilé, il peut déterminer ce qui pourrait être dans la mémoire , avec contenu en pouces, flotteurs, cordes, etc.). Comme l'a dit la première affiche, ces informations et le fonctionnement de ces symboles dépendent grandement de l'environnement et de la langue.

1
DavidG

Je pense qu'il y a deux questions principales à répondre ici:

1. Comment le débogueur sait qu'une exception s'est produite?

Lorsqu'une exception se produit dans un processus en cours de débogage, le débogueur est averti par le système d'exploitation avant que les gestionnaires d'exceptions utilisateur définis dans le processus cible aient la possibilité de répondre à l'exception. Si le débogueur choisit de ne pas gérer cette notification d'exception (de première chance), la séquence de distribution d'exception continue et le thread cible a alors la possibilité de gérer l'exception s'il le souhaite. Si l'exception SEH n'est pas gérée par le processus cible, le débogueur reçoit alors un autre événement de débogage, appelé notification de deuxième chance, pour l'informer qu'une exception non gérée s'est produite dans le processus cible. Source

enter image description here


2. Comment le débogueur sait comment s'arrêter sur un point d'arrêt?

Le réponse simplifié est: Lorsque vous placez un point d'arrêt dans le programme, le débogueur remplace votre code à ce point par une instruction int3 qui est un interruption logicielle . En conséquence, le programme est suspendu et le débogueur est appelé.

0
WeGoToMars