web-dev-qa-db-fra.com

Comment GDB suspend une exécution

Comme vous le savez peut-être, nous pouvons utiliser GDB et définir des points d'arrêt sur notre code pour suspendre l'exécution du débogage.

Ma question est de savoir comment GDB suspend un processus et vous permet de visualiser le contenu des registres à l'aide de i r par exemple. Ces registres ne sont-ils pas constamment utilisés par d'autres processus du système d'exploitation? comment ne sont-ils pas écrasés?

S'agit-il uniquement d'un instantané du contenu et non de données en direct?

16
Joe

Cela varie légèrement avec l'architecture, mais les points importants s'appliquent presque universellement:

  • L'interruption de service entraîne la sauvegarde de l'état du processeur (y compris les registres) avant d'exécuter l'ISR et sa restauration à la fermeture de l'ISR.

  • Si une routine de service d'interruption échange le contenu de l'emplacement de mémoire où ces registres sont enregistrés, elle peut effectuer un changement de contexte. Chaque thread a une région de mémoire où ses registres sont enregistrés lorsque le thread n'est pas en cours d'exécution.

  • Le changement de contexte est contrôlé par un planificateur de threads qui prend en compte si un thread attend les E/S, la synchronisation, quelle est sa priorité, la livraison du signal, etc. Souvent, il y a un compte de suspension qui est pris en compte dans.

  • Le débogueur peut incrémenter le nombre de suspensions, ce qui garantit que le thread n'est pas exécutable. Ensuite, il peut inspecter (et modifier) ​​la copie enregistrée des threads des registres.

24
Ben Voigt

En plus des excellentes informations de @BenVoigt, permettez-moi de faire quelques ajouts:

Un point d'arrêt est défini par le débogueur en remplaçant une valeur de code machine (une instruction ou une partie d'une instruction) dans le processus en cours de débogage avec une instruction de déroutement particulière à l'emplacement dans le code qui correspond à la ligne (source) souhaitée pour la rupture. Cette instruction d'interruption particulière est destinée à être utilisée comme point d'arrêt - le débogueur le sait, tout comme le système d'exploitation.

Lorsque le processus/thread débogué atteint l'instruction d'interruption, cela déclenche le processus décrit par @Ben, qui comprend la moitié d'un échange de contexte qui suspend le thread en cours d'exécution (qui inclut l'enregistrement de son état CPU en mémoire) pour une reprise ultérieure potentielle. Étant donné que cette interruption est une interruption de point d'arrêt, le système d'exploitation maintient le processus en cours de débogage suspendu en utilisant peut-être un mécanisme décrit par @Ben, et notifie et finalement reprend le débogueur.

Le débogueur utilise ensuite les appels système pour accéder à l'état enregistré du processus/thread suspendu en cours de débogage.

Pour exécuter (reprendre) la ligne de code qui s'est cassée (qui a maintenant l'instruction de déroutement particulière), le débogueur restaurera la valeur de code machine d'origine qu'il a écrasée avec l'instruction de déroutement de point d'arrêt, peut-être définir un autre déroutement ailleurs (par exemple, si une seule étape, ou l'utilisateur crée de nouveaux points d'arrêt), et marquez le processus/thread comme exécutable, en utilisant peut-être un mécanisme comme décrit @Ben.

Les détails réels peuvent être plus compliqués, en ce sens que le maintien d'un point d'arrêt de longue durée qui est atteint signifie faire quelque chose comme échanger l'interruption de point d'arrêt pour du code réel afin que la ligne puisse s'exécuter, puis échanger à nouveau le point d'arrêt ...

Ces registres ne sont-ils pas constamment utilisés par d'autres processus du système d'exploitation? comment ne sont-ils pas écrasés?

Comme @Ben le décrit, en utilisant la fonction de suspension/reprise de thread déjà existante (le changement de contexte/échange de multitâche ) qui permet aux processeurs d'être partagés par plusieurs processus/threads en utilisant le découpage temporel.

S'agit-il uniquement d'un instantané du contenu et non de données en direct?

C'est les deux. Étant donné que le thread qui a atteint le point d'arrêt est suspendu, il s'agit d'un instantané des données en direct (registres du processeur, etc.) au moment de la suspension, et du maître faisant autorité des valeurs de registre CPU à restaurer dans le processeur en cas de reprise du thread. Si vous utilisez l'interface utilisateur du débogueur pour lire et/ou modifier les registres du processeur (du processus en cours de débogage), il lira et/ou modifiera cet instantané/maître à l'aide d'appels système.

14
Erik Eidt

À strictement parler, au moins dans la plupart des cas typiques, gdb lui-même ne suspend pas l'exécution. Au lieu de cela, gdb demande à l'OS, et l'OS suspend l'exécution.

Cela pourrait initialement sembler être une distinction sans différence - mais honnêtement, il y a vraiment une différence. La différence est la suivante: cette capacité est déjà intégrée dans le système d'exploitation typique, car elle doit pouvoir suspendre et redémarrer l'exécution du thread de toute façon - lorsqu'un thread n'est pas planifié pour s'exécuter (par exemple, il a besoin d'une ressource qui n'est pas disponible actuellement), le système d'exploitation doit le suspendre jusqu'à ce qu'il puisse être planifié pour s'exécuter.

Pour ce faire, le système d'exploitation dispose généralement d'un bloc de mémoire réservé à chaque thread pour enregistrer l'état actuel de la machine. Lorsqu'il doit interrompre un thread, l'état actuel de la machine est enregistré dans cette zone. Lorsqu'il doit reprendre un thread, l'état de la machine est restauré à partir de cette zone.

Lorsque le débogueur a besoin de suspendre un thread, le système d'exploitation met ce thread en pause exactement de la même manière que pour d'autres raisons. Ensuite, pour lire l'état du thread en pause, le débogueur examine l'état enregistré du thread. Si vous modifiez l'état, le débogueur écrit dans l'état enregistré, puis prend effet lorsque le thread reprend.

5
Jerry Coffin