NOM
ptrace - Suivre un processus
SYNOPSIS
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);
L’appel système ptrace() fournit au processus parent un moyen de
contrôler l’exécution d’un autre processus et d’éditer son image
mémoire. L’utilisation primordiale de cette fonction est
l’implémentation de points d’arrêt pour le débogage, et pour suivre les
appels système.
Le père peut démarrer un suivi en appelant fork(2) et que le fils créé
fasse un PTRACE_TRACEME, suivi (en général) par un exec(3). Autrement,
le père peut commencer un suivi sur un processus existant en utilisant
PTRACE_ATTACH.
Le processus fils suivi s’arrêtera à chaque fois qu’un signal lui sera
délivré, même si le signal est ignoré (à l’exception de SIGKILL qui a
les effets habituels). Le père sera prévenu à son prochain wait(2) et
pourra inspecter et modifier le processus fils pendant son arrêt. Le
parent peut également faire continuer l’exécution de son fils,
éventuellement en ignorant le signal ayant déclenché l’arrêt, ou
envoyant un autre signal.
Quand le père a fini le suivi, il peut terminer le fils avec
PTRACE_KILL ou le faire continuer normalement, non suivi, avec
PTRACE_DETACH.
La valeur de l’argument request indique précisément l’action à
entreprendre.
PTRACE_TRACEME
Le processus en cours va être suivi par son père. Tout signal
(sauf SIGKILL) reçu par le processus l’arrêtera, et le père sera
notifié grâce à wait(2). De plus, les appels ultérieurs à
execve(2) par ce processus lui enverront SIGTRAP, ce qui donne
au père la possibilité de reprendre le contrôle avant que le
nouveau programme continue son exécution. Un processus ne doit
pas envoyer cette requête si son père n’est pas prêt à le
suivre. Dans cette requête pid, addr, et data sont ignorés.
La requête ci-dessus ne sert que dans le processus fils. Les autres ne
servent que dans le père. Par la suite, pid précise le fils sur lequel
agir. Pour les requêtes autres que PTRACE_KILL, le fils doit être
arrêté.
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
Lire un mot à l’adresse addr dans l’espace mémoire du fils et
renvoyer la valeur en résultat de ptrace(). Linux ne sépare pas
les espaces d’adressage de code et de données, ainsi ces deux
requêtes sont équivalentes. L’argument data est ignoré.
PTRACE_PEEKUSER
Lire un mot à l’adresse addr dans l’espace USER du fils, qui
contient les registres et diverses informations sur le processus
(voir <sys/user.h>). La valeur est renvoyée en résultat de
ptrace(). En principe, l’adresse doit être alignée sur une
frontière de mots, bien que cela varie selon les architectures.
Consultez la section NOTES. data est ignoré.
PTRACE_POKETEXT, PTRACE_POKEDATA
Copier un mot depuis l’adresse data de la mémoire du père vers
l’adresse addr de la mémoire du fils. Comme précédemment, les
deux requêtes sont équivalentes.
PTRACE_POKEUSER
Copier un mot depuis l’emplacement data de la mémoire du père
vers l’emplacement addr dans l’espace USER du processus fils.
Comme plus haut, les emplacements doivent être alignés sur une
frontière de mot. Pour maintenir l’intégrité du noyau, certaines
modifications de la zone USER sont interdites.
PTRACE_GETREGS, PTRACE_GETFPREGS
Copier les registres généraux ou du processeur en virgule
flottante, vers l’adresse data du père. Voir <sys/user.h> pour
les détails sur le format des données (addr est ignoré).
PTRACE_GETSIGINFO (depuis Linux 2.3.99-pre6)
Récupérer des informations sur le signal qui a causé l’arrêt.
Pour ce faire, copier une structure siginfo_t (voir
sigaction(2)) du fils à l’adresse data du père. L’argument addr
est ignoré.
PTRACE_SETREGS, PTRACE_SETFPREGS
Remplir les registres généraux ou du processeur en virgule
flottante, depuis le contenu de l’adresse data du père. Comme
pour PTRACE_POKEUSER certaines modifications sont interdites.
(addr est ignoré).
PTRACE_SETSIGINFO (depuis Linux 2.3.99-pre6)
Fixer des informations de signaux. Copier une structure
siginfo_t de l’adresse data dans le père vers le fils. Cela
n’affecte que les signaux qui auraient dû être délivrés au fils
et ont été interceptés à cause de ptrace(). Il peut être
difficile de différencier ces signaux normaux des signaux
générés par ptrace() lui-même. L’argument addr est ignoré.
PTRACE_SETOPTIONS (depuis Linux 2.4.6, voir remarques dans BOGUES)
Fixe les options de ptrace à partir de l’adresse data dans le
père (addr est ignoré). data est interprété comme un masque
d’options, qui est construit à partir des drapeaux suivants :
PTRACE_O_TRACESYSGOOD (Depuis Linux 2.4.6)
Lors d’un appel système, mettre à 1 le bit 7 du numéro de
signal (envoyer SIGTRAP|0x80). Cela permet au processus
utilisant ptrace() de faire la différence entre une
trappe normale, et une trappe due à un appel système.
PTRACE_O_TRACESYSGOOD peut ne pas marcher sur toutes les
architectures.
PTRACE_O_TRACEFORK (depuis Linux 2.5.46)
Arrêter le fils au prochain fork(2) avec SIGTRAP |
PTRACE_EVENT_FORK << 8 et commencer automatiquement à
suivre le nouveau processus créé, qui démarrera avec un
signal SIGSTOP. Le PID du nouveau processus peut être
récupéré avec PTRACE_GETEVENTMSG.
PTRACE_O_TRACEVFORK (depuis Linux 2.5.46)
Arrêter le fils au prochain appel vfork(2) avec SIGTRAP |
PTRACE_EVENT_VFORK << 8 et commencer automatiquement à
suivre le nouveau processus créé, qui démarrera avec un
signal SIGSTOP. Le PID du nouveau processus peut être
obtenu avec PTRACE_GETEVENTMSG.
PTRACE_O_TRACECLONE (depuis Linux 2.5.46)
Arrêter le fils au prochain appel clone(2) avec SIGTRAP |
PTRACE_EVENT_CLONE << 8 et commencer automatiquement à
suivre le nouveau processus cloné, qui démarrera avec un
signal SIGSTOP. Le PID du nouveau processus peut être
obtenu avec PTRACE_GETEVENTMSG. Cette option peut ne pas
intercepter tous les appels clone(2). Si le fils appelle
clone(2) avec l’attribut CLONE_VFORK, PTRACE_EVENT_VFORK
sera envoyé si PTRACE_O_TRACEVFORK est utilisé. Sinon, si
le fils appelle clone(2) avec SIGCHLD comme signal de
terminaison, PTRACE_EVENT_FORK sera envoyé si
PTRACE_O_TRACEFORK est utilisé.
PTRACE_O_TRACEEXEC (depuis Linux 2.5.46)
Arrêter le fils au prochain appel execve(2) avec SIGTRAP
| PTRACE_EVENT_EXEC << 8.
PTRACE_O_TRACEVFORKDONE (depuis Linux 2.5.60)
Arrêter le fils à la fin du prochain vfork(2) avec
SIGTRAP | PTRACE_EVENT_VFORK_DONE << 8.
PTRACE_O_TRACEEXIT (depuis Linux 2.5.60)
Arrêter le fils à sa terminaison avec SIGTRAP |
PTRACE_EVENT_EXIT << 8. Le code de retour du fils peut
être obtenu avec PTRACE_GETEVENTMSG. Cet arrêt sera
effectué tôt dans la terminaison du processus, alors que
les registres sont toujours disponibles, ce qui permet au
processus utilisant ptrace() de voir où la terminaison
s’est produite, alors que la notification de terminaison
normale a lieu à la fin de cette terminaison. Même si le
contexte est disponible, l’appelant ne peut pas empêcher
la terminaison du fils.
PTRACE_GETEVENTMSG (depuis Linux 2.5.46)
Récupérer un message (dans un unsigned long) concernant
l’événement ptrace qui vient d’arriver, en le plaçant à
l’adresse data dans le père. Pour PTRACE_EVENT_EXIT, il s’agit
du code de retour du fils. Pour PTRACE_EVENT_FORK,
PTRACE_EVENT_VFORK et PTRACE_EVENT_CLONE, il s’agit du PID du
nouveau processus. Depuis Linux 2.6.18, le PID du nouveau
processus est également disponible pour PTRACE_EVENT_VFORK_DONE.
(addr est ignoré.)
PTRACE_CONT
Redémarrer le processus fils arrêté. Si data est non nul et
autre que SIGSTOP, il est interprété comme un numéro de signal à
délivrer au fils; sinon aucun signal n’est délivré. On peut
ainsi contrôler si un signal envoyé au fils doit lui être
délivré ou non (addr est ignoré).
PTRACE_SYSCALL, PTRACE_SINGLESTEP
Redémarrer le processus fils arrêté comme pour PTRACE_CONT, mais
en s’arrangeant pour qu’il soit arrêté à la prochaine entrée ou
sortie d’un appel système, ou après la prochaine instruction,
respectivement. (Le fils sera aussi arrêté par l’arrivée d’un
signal). Du point de vue du père, le fils semblera être arrêté
par SIGTRAP. Ainsi, pour PTRACE_SYSCALL l’idée est d’inspecter
les arguments de l’appel système au premier arrêt puis de faire
un autre PTRACE_SYSCALL et d’inspecter la valeur de retour au
second arrêt. Le paramètre data est interprété comme pour
PTRACE_CONT. (addr est ignoré).
PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP (depuis Linux 2.6.14)
Pour PTRACE_SYSEMU, continuer puis s’arrêter lors du prochain
appel système, qui ne sera pas exécuté. Pour
PTRACE_SYSEMU_SINGLESTEP, faire la même chose, mais exécuter pas
à pas s’il ne s’agit pas d’un appel système. Cette fonction est
utilisée par des programmes comme User Mode Linux, qui veulent
émuler tous les appels système du fils. Le paramètre data est
interprété comme pour PTRACE_CONT. (addr est ignoré ; cet appel
n’est pas disponible sur toutes les architectures.)
PTRACE_KILL
Envoyer au fils un signal SIGKILL pour le terminer. (addr et
data sont ignorés).
PTRACE_ATTACH
Attacher le processus numéro pid, pour le suivre. Le
comportement du fils est le même que s’il avait fait un
PTRACE_TRACEME. Le processus appelant devient alors le père pour
de nombreuses choses (il recevra les notifications d’événements,
et sera indiqué comme le père dans un ps(1)). Mais getppid(2)
renverra dans le fils le PID du vrai père. Le processus fils va
recevoir un SIGSTOP, mais il ne sera peut-être pas stoppé tout
de suite, utilisez wait(2) pour attendre son arrêt (addr et data
sont ignorés).
PTRACE_DETACH
Relancer un processus fils comme avec PTRACE_CONT, en commençant
par le détacher, ce qui annule les effets de changement de
parenté de PTRACE_ATTACH et les effets de PTRACE_TRACEME. Le
processus ne sera plus suivi. Bien que cela soit involontaire,
sous Linux un processus suivi peut être détaché ainsi quelque
soit la méthode employée pour démarrer le suivi. (addr est
ignoré).
VALEUR RENVOYÉE
Pour les requêtes PTRACE_PEEK*, ptrace() renvoie la valeur réclamée et
zéro pour les autres requêtes, ou -1 en cas d’échec en remplissant
errno avec le code d’erreur. Comme la valeur renvoyée par une requête
PTRACE_PEEK* peut légitimement être -1, il faut vérifier errno après un
tel appel pour vérifier si une erreur s’est produite.
ERREURS
EBUSY (i386 seulement) Il y a eu une erreur lors de l’allocation ou de
la libération d’un registre de débogage.
EFAULT Tentative de lire ou écrire dans une zone mémoire invalide du
processus fils ou du père, probablement parce que la zone
n’était pas projetée ou accessible. Malheureusement sous Linux,
certaines variantes de cette erreur déclencheront EIO ou EFAULT
plus ou moins arbitrairement.
EINVAL Tentative d’utiliser une option invalide.
EIO La requête request n’est pas valide ou une tentative de lecture
ou d’écriture dans une zone invalide de mémoire a eu lieu. Il
peut également y avoir un problème d’alignement sur une
frontière de mot, ou une tentative de redémarrage en envoyant un
signal invalide.
EPERM Le processus indiqué ne peut pas être suivi. Cela peut être dû à
un manque de privilège du parent (la capacité nécessaire est
CAP_SYS_PTRACE). Les processus non-root ne peuvent pas suivre
les processus auxquels ils ne peuvent envoyer de signal, ou ceux
qui s’exécutent Set-UID/Set-GID. En outre, le processus visé
peut être déjà suivi, ou être init(8) (pid 1).
ESRCH Le processus indiqué n’existe pas, ou n’est pas suivi par
l’appelant, ou n’est pas arrêté (pour les requêtes qui en ont
besoin).
CONFORMITÉ
SVr4, BSD 4.3.
NOTES
Bien que les arguments de ptrace() soient interprétés comme dans le
prototype plus haut, la bibliothèque glibc déclare ptrace comme une
fonction variadique où seul l’argument request est fixé. Ceci signifie
que les arguments finaux inutiles peuvent être omis, bien que cela
utilise un comportement non documenté de gcc(1).
init(8), le processus numéro 1, ne peut pas être suivi.
La disposition du contenu de la mémoire et de la zone USER dépendent du
système d’exploitation et de l’architecture. Le décalage fourni et les
données renvoyées peuvent ne pas correspondre entièrement avec la
définition d’une structure struct user.
La taille d’un mot (« word ») est déterminée par la version du système
d’exploitation (par exemple 32 bits pour Linux-32-bits, etc.)
Le suivi peut engendrer des modifications subtiles dans le
fonctionnement du processus. Par exemple, si un processus est attaché
avec PTRACE_ATTACH, son père original ne peut plus recevoir les
notifications avec wait(2) lorsqu’il s’arrête, et il n’y a pas de moyen
de simuler cette notification.
Lorsque le parent reçoit un événement avec PTRACE_EVENT_* activé, le
fils n’est pas dans la procédure normale de réception de signal. Cela
signifie que le parent ne peut pas exécuter ptrace(PTRACE_CONT) avec un
signal ou ptrace(PTRACE_KILL). kill(2) avec un signal SIGKILL peut
cependant être utilisé pour tuer le processus fils à la réception d’un
de ces messages.
Cette page documente le fonctionnement actuel de ptrace() sous Linux.
Celui-ci peut varier sensiblement sur d’autres types d’Unix. De toute
façon, l’utilisation de ptrace() dépend fortement de l’architecture et
du système d’exploitation.
La page de manuel de SunOS décrit ptrace() comme un appel système
«unique and arcane », ce qu’il est. Le mécanisme de débogage basé sur
le système proc, présent dans Solaris 2 implémente un surensemble des
fonctionnalités de ptrace() de manière plus puissante et plus uniforme.
BOGUES
Sur les machines ayant des en-têtes du noyau 2.6, PTRACE_SETOPTIONS est
déclaré avec une valeur différente de celle du noyau 2.4. De ce fait,
les applications compilées avec ces en-têtes ne peuvent pas s’exécuter
sous des noyaux 2.4. Il est possible de contourner cette difficulté en
redéfinissant PTRACE_SETOPTIONS à PTRACE_OLDSETOPTIONS, si cette
dernière constante est définie.
VOIR AUSSI
gdb(1), strace(1), execve(2), fork(2), signal(2), wait(2), exec(3),
capabilities(7)
COLOPHON
Cette page fait partie de la publication 3.23 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent être trouvées à l’adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Cette page de manuel a été traduite et mise à jour par Christophe
Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis par
Alain Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
disposition sur http://manpagesfr.free.fr/.
Les mises à jour et corrections de la version présente dans Debian sont
directement gérées par Julien Cristau <jcristau@debian.org> et l’équipe
francophone de traduction de Debian.
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande « man -L C <section> <page_de_man> ».