xenial (2) ptrace.2.gz

Provided by: manpages-fr-dev_3.65d1p1-1_all bug

NOM

       ptrace - Suivre un processus

SYNOPSIS

       #include <sys/ptrace.h>

       long ptrace(enum __ptrace_request request, pid_t pid,
                   void *addr, void *data);

DESCRIPTION

       L'appel  système  ptrace()  fournit  à  un processus (l'« observateur ») un moyen d'observer et contrôler
       l'exécution d'un autre processus (l'« observé ») et d'examiner et éditer la mémoire et les  registres  de
       l'observé.  L'utilisation  principale  de  cette  fonction est l'implémentation de points d'arrêt pour le
       débogage, et pour suivre les appels système.

       Un observé doit d'abord être attaché à l'observateur. L'attachement et les commandes suivantes  sont  par
       thread :  dans  un  processus  multithreadé,  chaque  thread  peut  être  attaché  individuellement  à un
       observateur (éventuellement différent), ou être laissé détaché  et  donc  non  débogué.  Par  conséquent,
       l'« observé »  signifie  toujours « (un) thread », jamais « un processus (éventuellement multithreadé) ».
       Les commandes ptrace sont toujours envoyées à un observé spécifique en utilisant un appel de la forme

           ptrace(PTRACE_truc, pid, ...)

       où pid est l'identifiant de thread du thread Linux correspondant.

       (Remarquez que dans cette page, un « processus multithreadé » signifie un groupe de threads constitué  de
       threads créés en utilisant l'attribut CLONE_THREAD de clone(2).)

       Un  processus  peut  démarrer  un  suivi  en appelant fork(2) et faire en sorte que le fils créé fasse un
       PTRACE_TRACEME, suivi (en général) par un execve(2). Autrement, un processus peut commencer à  suivre  un
       autre processus en utilisant PTRACE_ATTACH ou PTRACE_SEIZE.

       L'observé  s'arrêtera  à  chaque  fois  qu'un  signal lui sera distribué, même si le signal est ignoré (à
       l'exception de SIGKILL qui a les effets habituels). L'observateur sera prévenu à son  prochain  appel  de
       waitpid(2)  (ou  un  des appels système liés à « wait ») ; cet appel renverra une valeur status contenant
       les  renseignements  indiquant  la  raison  de  l'arrêt  de  l'observé.  Lorsque  l'observé  est  arrêté,
       l'observateur peut utiliser plusieurs requêtes ptrace pour inspecter et modifier l'observé. L'observateur
       peut également laisser continuer l'exécution de l'observé, en ignorant  éventuellement  le  signal  ayant
       déclenché l'arrêt, ou même en envoyant un autre signal.

       Si  l'option PTRACE_O_TRACEEXEC n'est pas effective, tous les appels réussis d'execve(2) par le processus
       suivi déclencheront l'envoi d'un signal SIGTRAP, ce qui permet au père de reprendre le contrôle avant que
       le nouveau programme commence son exécution.

       Quand l'observateur a fini le suivi, il peut forcer l'observé à continuer normalement, en mode 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. Un processus ne devrait sans doute  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 PTRACE_TRACEME  ne  sert  qu'à  l'observé.  Les  requêtes  restantes  ne  servent  qu'à
              l'observateur.  Par  la  suite,  pid précise l'identifiant de thread de l'observé sur lequel agir.
              Pour les requêtes différentes de PTRACE_ATTACH,  PTRACE_SEIZE,  PTRACE_INTERRUPT  et  PTRACE_KILL,
              l'observé doit être arrêté.

       PTRACE_PEEKTEXT, PTRACE_PEEKDATA
              Lire  un  mot  à  l'adresse  addr dans l'espace mémoire de l'observé et le renvoyer en résultat de
              l'appel ptrace(). Linux ne sépare pas les espaces d'adressage de code et de données, donc ces deux
              requêtes sont équivalentes (data est ignoré, consultez la section NOTES).

       PTRACE_PEEKUSER
              Lire  un  mot  à  la  position addr dans l'espace USER de l'observé, qui contient les registres et
              divers renseignements 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é,  consultez  la  section
              NOTES).

       PTRACE_POKETEXT, PTRACE_POKEDATA
              Copier  un  mot  depuis  l'adresse  data  de la mémoire de l'observateur vers l'adresse addr de la
              mémoire de l'observé. Comme pour  PTRACE_PEEKTEXT  et  PTRACE_PEEKDATA,  ces  deux  requêtes  sont
              équivalentes.

       PTRACE_POKEUSER
              Copier  un  mot  depuis  l'emplacement data de la mémoire de l'observateur vers l'emplacement addr
              dans l'espace USER de l'observé. Comme pour PTRACE_PEEKUSER, 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 de l'observé,  vers  l'adresse
              data  de l'observateur. Consultez <sys/user.h> pour les détails sur le format de ces données (addr
              est ignoré). Remarquez que les systèmes SPARC ont la  signification  de  data  et  addr  inversée,
              c'est-à-dire  que data est ignoré et les registres sont copiés vers l'adresse addr. PTRACE_GETREGS
              et PTRACE_GETFPREGS ne sont pas présents sur toutes les architectures.

       PTRACE_GETREGSET (depuis Linux 2.6.34)
              Lire les registres de l'observé. addr indique, de manière dépendante de l'architecture, le type de
              registres  à  lire.  NT_PRSTATUS (avec une valeur numérique de 1) a pour conséquence habituelle la
              lecture de registres généraux. Si le processeur a, par exemple, des registres en virgule flottante
              ou en vecteur, ils peuvent être récupéré en configurant addr à la constante NT_foo correspondante.
              data pointe vers une struct iovec, qui décrit l'emplacement et la taille du tampon de destination.
              Le noyau modifie iov.len au retour pour indiquer le véritable nombre d'octets renvoyés.

       PTRACE_SETREGS, PTRACE_SETFPREGS
              Modifier  les  registres  généraux  ou  du  processeur  en  virgule flottante de l'observé, depuis
              l'adresse data de l'observateur. Comme pour PTRACE_POKEUSER, certaines modifications de  registres
              généraux  pourraient  être  interdites  (addr est ignoré). Remarquez que les systèmes SPARC ont la
              signification de data et addr inversée, c'est-à-dire que data est ignoré  et  les  registres  sont
              copiés  depuis  l'adresse addr. PTRACE_SETREGS et PTRACE_SETFPREGS ne sont pas présents sur toutes
              les architectures.

       PTRACE_SETREGSET (depuis Linux 2.6.34)
              Modifier  les  registres  de  l'observé.  La  signification  de  addr  et  data  est  analogue   à
              PTRACE_GETREGSET.

       PTRACE_GETSIGINFO (depuis Linux 2.3.99-pre6)
              Récupérer  des  renseignements  sur  le  signal  qui a provoqué l'arrêt. Pour ce faire, copier une
              structure siginfo_t (consultez sigaction(2)) de l'observé à l'adresse data de l'observateur  (addr
              est ignoré).

       PTRACE_SETSIGINFO (depuis Linux 2.3.99-pre6)
              Définir  les  renseignements  de  signaux :  copier  une  structure siginfo_t de l'adresse data de
              l'observateur vers l'observé. Cela n'affecte que les signaux qui auraient  dû  être  distribués  à
              l'observé et ont été interceptés à cause de ptrace(). Différencier ces signaux normaux des signaux
              créés par ptrace() lui-même peut être délicat (addr est ignoré).

       PTRACE_PEEKSIGINFO (depuis Linux 3.10)
              Récupérer les structures siginfo_t sans supprimer les signaux d’une file  d’attente.  addr  pointe
              vers  une  structure ptrace_peeksiginfo_args qui indique la position ordinale à partir de laquelle
              la copie des signaux devrait commencer et le nombre de signaux à copier. Les structures  siginfo_t
              sont  copiées  dans  le  tampon pointé par data. La valeur de retour contient le nombre de signaux
              copiés (zéro indique qu’il n’y a pas de signal correspondant à  la  position  ordinale  indiquée).
              Dans  les  structures  siginfo renvoyées, le champ si_code contient des renseignements (__SI_CHLD,
              __SI_FAULT, etc.) qui ne sont sinon pas exposés à l’espace utilisateur.

                 struct ptrace_peeksiginfo_args {
                     u64 off;    /* Position ordinale dans la file d’attente
                                    où commencer la copie de signaux */
                     u32 flags;  /* PTRACE_PEEKSIGINFO_SHARED ou 0 */
                     s32 nr;     /* Nombre de signaux à copier */
                 };

                 Actuellement, seul l’attribut PTRACE_PEEKSIGINFO_SHARED permet de vider les signaux de la  file
                 de signaux par processus. Si cet attribut n’est pas défini, les signaux sont lus depuis la file
                 par thread du thread indiqué.

       PTRACE_GETSIGMASK (depuis Linux 3.11)
              Placer une copie du masque des signaux bloqués (consultez sigprocmask(2)) dans  le  tampon  pointé
              par data qui devrait être un pointeur vers un tampon de type sigset_t. L’argument addr contient la
              taille du tampon pointé par data (c’est-à-dire sizeof(sigset_t)).

       PTRACE_SETSIGMASK (depuis Linux 3.11)
              Modifier le masque des signaux bloqués (consultez sigprocmask(2)) à la  valeur  indiquée  dans  le
              tampon  pointé  par  data qui devrait être un pointeur vers un tampon de type sigset_t. L’argument
              addr contient la taille du tampon pointé par data (c’est-à-dire sizeof(sigset_t)).

       PTRACE_SETOPTIONS (depuis Linux 2.4.6, consultez les remarques de BOGUES)
              Définir les options de ptrace à partir de l'adresse data (addr est ignoré).  data  est  interprété
              comme un masque d'options, qui est construit à partir des attributs suivants.

              PTRACE_O_EXITKILL (depuis Linux 3.8)
                     Si  l'observateur  définit  cet attribut, un signal SIGKILL sera envoyé à tous les observés
                     quand l'observateur se termine. Cet option est utile pour les gardiens ptrace  qui  veulent
                     s'assurer que les observés ne peuvent jamais échapper au contrôle de l'observateur.

              PTRACE_O_TRACECLONE (depuis Linux 2.5.46)
                     Arrêter  l'observé  au  prochain  clone(2) et commencer automatiquement à suivre le nouveau
                     processus cloné, qui démarrera avec un signal SIGSTOP, ou PTRACE_EVENT_STOP si PTRACE_SEIZE
                     est utilisé. Un waitpid(2) par l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

                     Cette  option  peut  ne  pas  intercepter  tous  les  appels clone(2). Si l'observé appelle
                     clone(2) avec l'attribut CLONE_VFORK, PTRACE_EVENT_VFORK sera envoyé si PTRACE_O_TRACEVFORK
                     est utilisé. Sinon, si l'observé 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 l'observé au prochain execve(2).  Un  waitpid(2)  par  l'observateur  renverra  une
                     valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8))

                     Si  le  thread en cours d'exécution n'est pas un leader de groupe de threads, l'identifiant
                     de thread est réinitialisé à l'identifiant du leader de groupe de threads avant cet  arrêt.
                     Depuis   Linux 3.0,   le   premier   identifiant   de   thread   peut  être  récupéré  avec
                     PTRACE_GETEVENTMSG.

              PTRACE_O_TRACEEXIT (depuis Linux 2.5.60)
                     Arrêter l'observé à la terminaison. Un waitpid(2) par  l'observateur  renverra  une  valeur
                     status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))

                     L'état de fin de l'observé peut être récupéré avec PTRACE_GETEVENTMSG.

                     L'observé  est  arrêté  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'observateur  ne  peut  pas
                     empêcher la terminaison à ce moment là.

              PTRACE_O_TRACEFORK (depuis Linux 2.5.46)
                     Arrêter  l'observé  au  prochain  fork(2)  et commencer automatiquement à suivre le nouveau
                     processus créé, qui démarrera avec un signal SIGSTOP, ou PTRACE_EVENT_STOP si  PTRACE_SEIZE
                     est utilisé. Un waitpid(2) par l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

              PTRACE_O_TRACESYSGOOD (depuis Linux 2.4.6)
                     Lors  des  interceptions  d'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
                     les interceptions normales et celles provoquées par un appel système. PTRACE_O_TRACESYSGOOD
                     peut ne pas fonctionner sur toutes les architectures.

              PTRACE_O_TRACEVFORK (depuis Linux 2.5.46)
                     Arrêter l'observé au prochain vfork(2) et commencer automatiquement  à  suivre  le  nouveau
                     processus  créé, qui démarrera avec un signal SIGSTOP, ou PTRACE_EVENT_STOP si PTRACE_SEIZE
                     est utilisé. Un waitpid(2) par l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

              PTRACE_O_TRACEVFORKDONE (depuis Linux 2.5.60)
                     Arrêter l'observé à la fin du prochain vfork(2). Un waitpid(2) par  l'observateur  renverra
                     une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8))

                     Le   PID   du   nouveau   processus   peut   (depuis   Linux 2.6.18)   être  récupéré  avec
                     PTRACE_GETEVENTMSG.

       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 de l'observateur. Pour PTRACE_EVENT_EXIT, il s'agit du code de retour
              de   l'observé.   Pour   PTRACE_EVENT_FORK,   PTRACE_EVENT_VFORK,    PTRACE_EVENT_VFORK_DONE    et
              PTRACE_EVENT_CLONE, il s'agit du PID du nouveau processus (addr est ignoré).

       PTRACE_CONT
              Redémarrer  l'observé  arrêté.  Si data est non nul, il est interprété comme un numéro de signal à
              distribuer à l'observé ; sinon aucun signal n'est distribué. L'observateur peut ainsi contrôler si
              un signal envoyé à l'observé doit lui être distribué ou non (addr est ignoré).

       PTRACE_SYSCALL, PTRACE_SINGLESTEP
              Redémarrer  l'observé 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  (l'observé  sera  aussi  arrêté  par  l'arrivée  d'un  signal). Du point de vue de
              l'observateur, l'observé 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 de l'observé. Le paramètre data  est  interprété
              comme  pour  PTRACE_CONT.  L'argument  addr  est  ignoré.  Ces  requêtes  ne  sont  pour l'instant
              disponibles que sur x86.

       PTRACE_LISTEN (depuis Linux 3.4)
              Redémarrer l'observé arrêté, mais en l'empêchant de s'exécuter. L'état résultant de l'observé  est
              similaire  a  celui  d'un  processus  qui  a  été arrêté par un SIGSTOP (ou autre signal d'arrêt).
              Consultez la sous-section Arrêt-groupe pour des renseignements supplémentaires.  PTRACE_LISTEN  ne
              fonctionne que sur les observés attachés par PTRACE_SEIZE.

       PTRACE_KILL
              Envoyer à l'observé un signal SIGKILL pour le terminer (addr et data sont ignorés).

              Cette  opération  est  obsolète,  ne l'utilisez pas. À la place, envoyez un SIGKILL directement en
              utilisant kill(2) ou tgkill(2). Le problème avec PTRACE_KILL est  qu'il  nécessite  que  l'observé
              soit en arrêt-distribution-signal, sinon cela risque de ne pas fonctionner (c'est-à-dire risque de
              se terminer avec succès sans tuer l'observé). En revanche, envoyer SIGKILL directement  n'est  pas
              concerné par cette limite.

       PTRACE_INTERRUPT (depuis Linux 3.4)
              Arrêter  un observé. Si l’observé est en cours d’exécution ou en sommeil dans l’espace utilisateur
              et que PTRACE_SYSCALL est effectif, l’appel système est interrompu et l'arrêt-sortie-appel-système
              est signalé (l’appel système interrompu est redémarré quand l’observé est redémarré). Si l’observé
              avait déjà été arrêté par un signal et que PTRACE_LISTEN lui avait été envoyé, l’observé  s’arrête
              avec  PTRACE_EVENT_STOP  et  WSTOPSIG(status)  renvoie  le signal d’arrêt. Si n’importe quel autre
              arrêt-ptrace est créé en même temps (par exemple, si  un  signal  est  envoyé  à  l’observé),  cet
              arrêt-ptrace  arrive.  Si  rien  de  ce qui précède ne s’applique (par exemple si l’observé est en
              cours d’exécution en espace utilisateur), il s’arrête avec PTRACE_EVENT_STOP avec WSTOPSIG(status)
              == SIGTRAP. PTRACE_INTERRUPT ne fonctionne que sur les observés attachés par PTRACE_SEIZE.

       PTRACE_ATTACH
              Attacher  le  processus  numéro  pid, pour le suivre. L'observé va recevoir un SIGSTOP, mais il ne
              sera peut-être pas arrêté tout de suite, utilisez waitid(2) pour attendre son arrêt. Consultez  la
              sous-section  Attachement  et détachement pour obtenir de plus amples renseignements (addr et data
              sont ignorés).

       PTRACE_SEIZE (depuis Linux 3.4)
              Attacher  au  processus  indiqué  par  pid,  faisant  de  lui  l'observé  du  processus  appelant.
              Contrairement  à  PTRACE_ATTACH,  PTRACE_SEIZE  n'arrête  pas le processus. Seul un processus sous
              PTRACE_SEIZE peut accepter les commandes PTRACE_INTERRUPT et PTRACE_LISTEN. addr doit  être  zéro.
              data contient un masque d'options de ptrace à activer immédiatement.

       PTRACE_DETACH
              Relancer l'observé arrêté comme avec PTRACE_CONT, mais en commençant par s'en détacher. Sous Linux
              un observé peut être détaché ainsi quelque soit la méthode employée pour démarrer le  suivi  (addr
              est ignoré).

   Mort sous ptrace
       Quand  un  processus  (éventuellement multithreadé) reçoit un signal pour le tuer (un dont la disposition
       est configurée à SIG_DFL et dont l'action par défaut est de tuer  le  processus),  tous  les  threads  se
       terminent. Chaque observé signale sa mort à son ou ses observateurs. La notification de cet événement est
       distribuée par waitpid(2).

       Remarquez que le signal tueur provoquera d'abord un arrêt-distribution-signal (sur un seul  observé)  et,
       seulement après être injecté par l'observateur (ou après être envoyé à un thread qui n'est pas suivi), la
       mort  du  signal   arrivera   sur   tous   les   observés   d'un   processus   multithreadé   (le   terme
       « arrêt-distribution-signal » est expliqué plus bas).

       SIGKILL  ne  génère  pas  d'arrêt-distribution-signal  et  l'observateur  ne  peut  par conséquent pas le
       supprimer. SIGKILL tue même à l'intérieur des appels systèmes (arrêt-sortie-appel-système n'est pas  créé
       avant  la mort par SIGKILL). L'effet direct est que SIGKILL tue toujours le processus (tout ses threads),
       même si certains threads du processus sont suivis avec ptrace.

       Quand l'observé appelle _exit(2), il signale sa mort à son observateur. Les autres threads  ne  sont  pas
       concernés.

       Quand  n'importe  quel thread exécute exit_group(2), tous les observés de son groupe de threads signalent
       leur mort à leur observateur.

       Si l'option PTRACE_O_TRACEEXIT  est  active,  PTRACE_EVENT_EXIT  arrivera  avant  la  mort  réelle.  Cela
       s'applique aux terminaisons avec exit(2), exit_group(2) et aux morts de signal (sauf SIGKILL), et lorsque
       les threads sont démolis par execve(2) dans un processus multithreadé.

       L'observateur ne peut pas assumer que l'observé arrêté-ptrace existe. L'observé risque  de  mourir  avant
       d'être  arrêté  dans  plusieurs cas (comme avec SIGKILL). Par conséquent, le tracé doit être préparé pour
       traiter une erreur ESRCH sur n'importe  quel  opération  ptrace.  Malheureusement,  la  même  erreur  est
       renvoyée  si l'observé existe mais n'est pas arrêté-ptrace (pour les commandes qui nécessitent un observé
       arrêté), ou s'il n'est pas suivi par le processus qui a envoyé l'appel ptrace. L'observateur doit  garder
       une  trace  de  l'état  arrêté  ou en fonctionnement de l'observé, et interpréter ESRCH comme « l'observé
       s'est achevé de manière inattendue » seulement  s'il  sait  que  l'observé  est  effectivement  entré  en
       arrêt-ptrace.  Remarquez  qu'il  n'est pas garanti que waitpid(WNOHANG) signale de façon fiable l'état de
       mort de l'observé si une opération ptrace renvoie ESRCH. waitpid(WNOHANG)  pourrait  plutôt  renvoyer  0.
       Autrement dit, l'observé pourrait « ne pas être encore mort », mais déjà refuser des requêtes ptrace.

       L'observateur  ne  peut pas assumer que l'observé finit toujours sa vie en signalant WIFEXITED(status) ou
       WIFSIGNALED(status) ; dans certains cas ça n'arrive pas. Par exemple si un thread différent du leader  de
       groupe  de  threads  fait  un  execve(2),  il disparaît ; son PID ne sera plus jamais vu, tous les arrêts
       suivants de ptrace seront signalés sous le PID du leader de groupe de threads.

   États arrêtés
       Deux états existent pour un observé : en cours d'exécution ou à l'arrêt. Du point de vue  de  ptrace,  un
       observé  qui  est bloqué dans un appel système (comme read(2), pause(2), etc.) est néanmoins considéré en
       cours d’exécution, même si l’observé est bloqué depuis longtemps. L’état de l’observé après PTRACE_LISTEN
       est  en  quelque sorte une zone d’ombre : il n’est dans aucun arrêt-ptrace (les commandes ptrace n’auront
       aucun effet sur lui et il  distribuera  des  notifications  waitpid(2)),  mais  il  pourrait  aussi  être
       considéré  « arrêté »  parce  qu’il n’est pas en train d’exécuter des instructions (pas de programmation)
       et, s’il était en arrêt-groupe avant PTRACE_LISTEN, il ne répondra pas  aux  signaux  avant  de  recevoir
       SIGCONT.

       De  nombreuses  sortes  d'états sont possibles quand l'observé est arrêté, et les discussions dans ptrace
       sont souvent confondues. Par conséquent, l'utilisation de termes précis est importante.

       Dans cette page de manuel, tous les états d'arrêt  dans  lesquels  l'observé  est  prêt  à  accepter  des
       commandes  ptrace  de  l'observateur  sont  appelés arrêts-ptrace. Les arrêts-ptrace peuvent ensuite être
       sous-divisés en arrêt-distribution-signal, arrêt-groupe, arrêt-appel-système, etc. Ces états d'arrêt sons
       décrits en détail ci-dessous.

       Lorsque  l'observé  en  cours  d'exécution  entre  en arrêt-ptrace, il avise son observateur en utilisant
       waitpid(2) (ou un des autres appels système « wait »). La plupart de cette page  de  manuel  suppose  que
       l'observateur attend avec :

           pid = waitpid(pid_ou_moins_1, &status, __WALL);

       Les   observés   arrêtés-ptrace  sont  signalés  comme  renvoyés  avec  un  pid  strictement  positif  et
       WIFSTOPPED(status) vrai.

       L'attribut __WALL ne contient pas les attributs WSTOPPED et WEXITED, mais implique leur fonctionnalité.

       La  configuration  de  l'attribut  WCONTINUED  en  appelant  waitpid(2)  n'est  pas  conseillée :  l'état
       « exécuté » est relatif au processus et l'utiliser peut embrouiller le vrai père de l'observé.

       Utiliser  l'attribut  WNOHANG  pourrait forcer waitpid(2) à renvoyer 0 (« aucun résultat d'attente encore
       disponible ») même si l'observateur sait qu'il devrait y avoir une notification. Exemple :

           errno = 0;
           ptrace(PTRACE_CONT, pid, 0L, 0L);
           if (errno == ESRCH) {
               /* l'observé est mort */
               r = waitpid(observé, &status, __WALL | WNOHANG);
               /* r peut encore être 0 ici ! */
           }

       Les  sortes  d'arrêts-ptrace  suivants  existent :  arrêts-distribution-signal,   arrêts-groupe,   arrêts
       PTRACE_EVENT  et arrêts-appel-système. Ils sont signalés par waitpid(2) avec WIFSTOPPED(status) vrai. Ils
       peuvent être distingués en examinant la valeur status>>8, et en cas d'ambiguïté  dans  cette  valeur,  en
       faisant  une  requête  PTRACE_GETSIGINFO  (remarque : la macro WSTOPSIG(status) ne peut pas être utilisée
       pour réaliser cet examen, car elle renvoie la valeur (status>>8) & 0xff.)

   Arrêt-distribution-signal
       Quand un processus (éventuellement multithreadé) reçoit n'importe quel  signal  sauf  SIGKILL,  le  noyau
       choisi  un thread arbitraire pour traiter le signal (si le signal est créé avec tgill(2), le thread cible
       peut  être  explicitement  choisi  par  l'appelant).  Si  le  thread  choisi  est  suivi,  il  entre   en
       arrêt-distribution-signal.  À  ce  moment  là, le signal n'est pas encore distribué au processus, et peut
       être supprimé par l'observateur. Si l'observateur ne supprime  pas  le  signal,  il  passe  le  signal  à
       l'observé  lors  de la requête suivante de redémarrage de ptrace. Cette deuxième étape de distribution de
       signal est appelée injection de signal dans cette page de manuel. Remarquez que si le signal est  bloqué,
       l'arrêt-distribution-signal  n'arrive pas avant que le signal soit débloqué, à l'exception habituelle que
       SIGSTOP ne peut pas être bloqué.

       L'arrêt-distribution-signal  est  respecté  par  l'observateur  tant   que   waitpid(2)   retourne   avec
       WIFSTOPPED(status)  vrai,  avec  le  signal  renvoyé par WSTOPSIG(status). Si le signal est SIGTRAP, cela
       pourrait être un arrêt-ptrace de nature  différente ;  consultez  les  sections  Arrêts-appel-système  et
       execve(2)  sous  ptrace  plus  bas pour obtenir de plus amples précisions. Si WSTOPSIG(status) renvoie un
       signal d'arrêt, cela pourrait être un arrêt-groupe ; voir ci-dessous.

   Injection et suppression de signal
       Après un arrêt-distribution-signal respecté par l'observateur, l'observateur devrait redémarrer l'observé
       avec l'appel

           ptrace(PTRACE_redémarrer, pid, 0, sig)

       où  PTRACE_redémarrer  est une des requêtes ptrace de redémarrage. Si sig est 0, alors aucun signal n'est
       distribué. Sinon, le signal sig est distribué. Cette opération est appelée injection de signal dans cette
       page de manuel, pour la distinguer de l'arrêt-distribution-signal.

       La  valeur  de  sig  peut  être  différente  de  celle de WSTOPSIG(status) : l'observateur peut provoquer
       l'injection d'un autre signal.

       Remarquez qu'un signal supprimé provoque toujours un retour prématuré des appels système.  Dans  ce  cas,
       les  appels  système  seront  redémarrés :  l'observateur  forcera l'observé à réexécuter l'appel système
       interrompu (ou l'appel système restart_syscall(2) pour les quelques appels système qui utilisent un autre
       mécanisme  de  redémarrage)  si  l'observateur  utilise  PTRACE_SYSCALL.  Même  les appels système (comme
       poll(2)) qui ne sont pas redémarrables après signal sont  redémarré  après  la  suppression  du  signal ;
       cependant,  des  bogues  du  noyau  existent et certains appels système échouent avec EINTR même si aucun
       signal observable n'est injecté dans l'observé.

       Lors du redémarrage des commandes ptrace émises dans d'autres arrêts-ptrace qu'arrêt-distribution-signal,
       l'injection  de signal n'est pas garantie, même si sig est non nul. Aucune erreur n'est signalée ; un sig
       non nul risque simplement d'être ignoré. Les utilisateurs de ptrace ne devraient pas essayer  de  « créer
       un nouveau signal » de cette façon : utilisez plutôt tgkill(2).

       Le  fait  que  des requêtes d'injection de signal puissent être ignorées lors du redémarrage de l'observé
       après des arrêts ptrace qui ne sont pas des arrêts-distribution-signal est une source de  confusion  pour
       les  utilisateurs  de  ptrace.  Un  scénario  typique  est que l'observateur remarque un arrêt-groupe, le
       confonde avec un arrêt-distribution-signal, et redémarre l'observé avec

           ptrace(PTRACE_restart, pid, 0, stopsig)

       dans le but d'injecter stopsig, alors que stopsig sera ignoré et que l'observé continuera de fonctionner.

       Le signal SIGCONT a pour effet de bord de réveiller (tous les threads d'un processus  arrêté-groupe.  Cet
       effet de bord arrive avant un arrêt-distribution-signal. L'observateur ne peut pas supprimer cet effet de
       bord (il ne peut que supprimer l'injection de signal, qui force seulement le gestionnaire de SIGCONT à ne
       pas  être  exécuté dans l'observé, si un gestionnaire de ce type est installé). En fait, le réveil depuis
       un arrêt-groupe pourrait être suivi par un arrêt-distribution-signal pour le ou les signaux différents de
       SIGCONT,  s'ils  étaient en attente quand SIGCONT a été distribué. Autrement dit, SIGCONT pourrait ne pas
       être le premier signal remarqué par l'observé après avoir été envoyé.

       L'arrêt de signaux force (tous les threads d')un processus à entrer en arrêt-groupe. Cet  effet  de  bord
       arrive après une injection de signal, et peut par conséquent être supprimé par l'observateur.

       Sous Linux 2.4 et les versions précédentes, le signal SIGSTOP ne pouvait pas être injecté.

       PTRACE_GETSIGINFO  peut  être  utilisé  pour  récupérer  une structure siginfo_t qui correspond au signal
       distribué. PTRACE_SETSIGINFO pourrait être utilisé pour le modifier. Si PTRACE_SETSIGINFO a  été  utilisé
       pour  modifier  siginfo_t,  le  champ  si_signo et le paramètre sig de la commande de redémarrage doivent
       correspondre, sinon le résultat est indéfini.

   Arrêt-groupe
       Quand un processus (éventuellement multithreadé) reçoit un signal d'arrêt, tous les  threads  s'arrêtent.
       Si  certains threads sont suivis, ils entrent en arrêt-groupe. Remarquez que le signal d'arrêt provoquera
       d'abord un arrêt-distribution-signal (sur un seul observé) et, seulement  après  avoir  été  injecté  par
       l'observateur (ou après avoir été envoyé à un thread qui n'est pas suivi), l'arrêt-groupe sera initié sur
       tous les observés d'un processus  multithreadé.  Comme  d'habitude,  tous  les  observés  signalent  leur
       arrêt-groupe séparément à l'observateur correspondant.

       L'arrêt-groupe  est respecté par l'observateur tant que waitpid(2) retourne avec WIFSTOPPED(status) vrai,
       avec le signal d'arrêt disponible par l'intermédiaire de WSTOPSIG(status). Le même résultat  est  renvoyé
       par d'autres classes d'arrêts-ptrace, par conséquent la méthode conseillée est de réaliser l'appel

           ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo)

       L'appel  peut  être  évité si le signal n'est pas SIGSTOP, SIGTSTP, SIGTTIN ou SIGTTOU ; seuls ces quatre
       signaux sont des signaux d'arrêt. Si l'observateur voit autre chose, ce ne peut pas être un arrêt-groupe.
       Sinon, l'observateur doit appeler PTRACE_GETSIGINFO. Si PTRACE_GETSIGINFO échoue avec EINVAL, alors c'est
       définitivement un arrêt-groupe (d'autres codes d'échec sont possibles, comme ESRCH (« pas de processus de
       ce type ») si un SIGKILL a tué l'observé).

       Si l’observé était attaché en utilisant PTRACE_SEIZE, un arrêt-groupe est indiqué par PTRACE_EVENT_STOP :
       status>>16 == PTRACE_EVENT_STOP.  Cela  permet  la  détection  d’arrêts-groupe  sans  nécessiter  d’appel
       PTRACE_GETSIGINFO supplémentaire.

       Depuis  Linux 2.6.38,  après  que  l'observateur  a vu l'arrêt-ptrace de l'observé et jusqu'à ce qu'il le
       redémarre ou le tue, l'observé ne fonctionnera pas, et n'enverra  pas  de  notification  (sauf  mort  par
       SIGKILL) à l'observateur, même si l'observateur entre dans un autre appel waitpid(2).

       Le  comportement  du  noyau  décrit  dans  le  paragraphe  précédent  pose  un  problème  avec la gestion
       transparente de signaux d'arrêt. Si l'observateur redémarre l'observé après un  arrêt-groupe,  le  signal
       d'arrêt  est  effectivement  ignoré  — l'observé  ne reste pas arrêté, il fonctionne. Si l'observateur ne
       redémarre pas l'observé avant d'entrer dans le prochain  waitpid(2),  les  signaux  SIGCONT  suivants  ne
       seront  pas  signalés  à  l'observateur ;  cela pourrait forcer des signaux SIGCONT à être sans effet sur
       l'observé.

       Depuis Linux 3.4, une méthode permet d'éviter ce problème : à  la  place  de  PTRACE_CONT,  une  commande
       PTRACE_LISTEN  peut  être  utilisée pour redémarrer un observé de façon à ce qu'il ne s'exécute pas, mais
       attende un nouvel événement qu'il peut signaler à l'aide de waitpid(2) (comme s'il était redémarré par un
       SIGCONT).

   Arrêts PTRACE_EVENT
       Si  l'observateur  configure  des  options  PTRACE_O_TRACE_*,  l'observé entrera en arrêts-ptrace appelés
       arrêts PTRACE_EVENT.

       Les  arrêts  PTRACE_EVENT  sont  respectés  par  l'observateur  tant   que   waitpid(2)   retourne   avec
       WIFSTOPPED(status),  et  que  WSTOPSIG(status)  renvoie SIGTRAP. Un bit supplémentaire est configuré dans
       l'octet le plus haut du mot d'état : la valeur status>>8 sera

           (SIGTRAP | PTRACE_EVENT_truc << 8).

       Les événements suivants existent.

       PTRACE_EVENT_VFORK
              Arrêt avant de revenir de vfork(2) ou clone(2) avec l'attribut CLONE_VFORK.  Quand  l'observé  est
              continué  après  cet  arrêt,  il  attendra  une sortie ou exécution du fils avant de continuer son
              exécution (autrement dit, le comportement normal avec vfork(2)).

       PTRACE_EVENT_FORK
              Arrêt avant de revenir de fork(2) ou clone(2) avec le signal de sortie configuré à SIGCHLD.

       PTRACE_EVENT_CLONE
              Arrêt avant de revenir de clone(2).

       PTRACE_EVENT_VFORK_DONE
              Arrêt avant de revenir de vfork(2) ou clone(2) avec l'attribut CLONE_VFORK, mais après que le fils
              a débloqué son observé par sortie ou exécution.

       Pour  les quatre arrêts décrits ci-dessus, l'arrêt arrive dans le père (c'est-à-dire l'observé), pas dans
       le nouveau thread créé. PTRACE_GETEVENTMSG permet de récupérer l'identifiant du nouveau thread.

       PTRACE_EVENT_EXEC
              Arrêt avant le  retour  d'execve(2).  Depuis  Linux 3.0,  PTRACE_GETEVENTMSG  renvoie  le  premier
              identifiant de thread.

       PTRACE_EVENT_EXIT
              Arrêt  avant  la  sortie  (y compris la mort depuis exit_group(2)), la mort du signal ou la sortie
              provoquée par execve(2) dans un  processus  multithreadé.  PTRACE_GETEVENTMSG  renvoie  l'état  de
              sortie.  Les  registres peuvent être examinés (contrairement à quand une « vraie » sortie arrive).
              L'observé est toujours actif ; il a besoin  de  PTRACE_CONT  ou  PTRACE_DETACH  pour  terminer  sa
              sortie.

       PTRACE_EVENT_STOP
              Arrêt  causé  par  la commande PTRACE_INTERRUPT, ou arrêt-groupe, ou arrêt-ptrace initial quand un
              nouveau  fils  est  attaché  (seulement  s’il  est  attaché   en   utilisant   PTRACE_SEIZE),   ou
              PTRACE_EVENT_STOP si PTRACE_SEIZE était utilisé.

       PTRACE_GETSIGINFO  sur  les  arrêts  PTRACE_EVENT renvoie SIGTRAP dans si_signo, avec si_code configuré à
       (event<<8) | SIGTRAP.

   Arrêts-appel-système
       Si l'observé était redémarré par PTRACE_SYSCALL,  l'observé  entre  en  arrêt-entrée-appel-système  juste
       avant   d'entrer   dans   n'importe  quel  appel  système.  Si  l'observateur  redémarre  l'observé  avec
       PTRACE_SYSCALL, l'observé entre en arrêt-sortie-appel-système quand l'appel système est terminé, ou  s'il
       est  interrompu  par  un  signal  (c'est-à-dire  qu'un arrêt-distribution-signal n'arrive jamais entre un
       arrêt-entrée-appel-système     et     un      arrêt-sortie-appel-système :      il      arrive      après
       l'arrêt-sortie-appel-système).

       D'autres  possibilités sont que l'observé pourrait s'arrêter dans un arrêt PTRACE_EVENT, sortir (s'il est
       entré en _exit(2) ou exit_group(2)), être tué par SIGKILL ou mourir  silencieusement  (s'il  s'agit  d'un
       leader  de  groupe de threads, que l'execve(2) est arrivé dans un autre thread et que ce thread n'est pas
       suivi par le même observateur ; cette situation sera abordée plus tard).

       Les arrêt-entrée-appel-système et arrêt-sortie-appel-système sont respectés par  l'observateur  tant  que
       waitpid(2)  retourne  avec  WIFSTOPPED(status)  vrai,  et que WSTOPSIG(status) donne SIGTRAP. Si l'option
       PTRACE_O_TRACESYSGOOD était configurée  par  l'observateur,  alors  WSTOPSIG(status)  donnera  la  valeur
       (SIGTRAP | 0x80).

       Les arrêts-appel-système peuvent être distingués d'un arrêt-distribution-signal avec SIGTRAP en demandant
       PTRACE_GETSIGINFO pour les cas suivants.

       si_code <= 0
              SIGTRAP a été distribué comme résultat d'une action en espace utilisateur, par exemple,  un  appel
              système (tgkill(2), kill(2), sigqueue(3), etc.), l'expiration d'un minuteur POSIX, la modification
              d'état sur une file de messages POSIX où la fin d'une requête d'E/S asynchrone.

       si_code == SI_KERNEL (0x80)
              SIGTRAP a été envoyé par le noyau.

       si_code == SIGTRAP ou si_code == (SIGTRAP|0x80)
              C'est un arrêt-appel-système.

       Cependant, les arrêts-appel-système arrivent très souvent (deux  fois  par  appel  système)  et  réaliser
       PTRACE_GETSIGINFO pour chaque arrêt-appel-système pourrait être assez coûteux.

       Certaines  architectures  permettent  de  distinguer ces cas en examinant les registres. Par exemple, sur
       x86, rax == -ENOSYS en arrêt-entrée-appel-système. Puisque  SIGTRAP  (comme  tout  autre  signal)  arrive
       toujours après l'arrêt-sortie-appel-système et que rax ne contient à ce moment presque jamais -ENOSYS, le
       SIGTRAP ressemble à un « arrêt-appel-système qui n'est pas  un  arrêt-entrée-appel-système » ;  autrement
       dit,  il  ressemble  à  un  « arrêt-sortie-appel-système perdu » et peut être détecté de cette façon. Une
       telle détection est néanmoins fragile, elle est donc a éviter.

       L'utilisation  de  l'option  PTRACE_O_TRACESYSGOOD  est  la  méthode  conseillée  pour   distinguer   les
       arrêts-appel-système  des autres sortes d'arrêts-ptrace, puisqu'il est fiable et n'induit pas de perte de
       performances.

       Les arrêt-entrée-appel-système et arrêt-sortie-appel-système ne sont pas différentiables l'un de l'autre.
       L'observateur  doit  garder  une  trace  de  la  suite  d'arrêts-ptrace afin de ne pas mal interpréter un
       arrêt-entrée-appel-système  comme  un  arrêt-sortie-appel-système  ou  vice  versa.  La  règle  est   que
       l'arrêt-entrée-appel-système  est toujours suivi par un arrêt-sortie-appel-système, un arrêt PTRACE_EVENT
       ou la mort de l'observé ; aucune autre sorte d'arrêt-ptrace ne peut arriver entre-deux.

       Si suite à un arrêt-entrée-appel-système, l'observateur utilise une commande de redémarrage différente de
       PTRACE_SYSCALL, l'arrêt-sortie-appel-système n'est pas créé.

       PTRACE_GETSIGINFO  sur  les  arrêts-appel-système renvoie SIGTRAP dans si_signo, avec si_code configuré à
       SIGTRAP ou (SIGTRAP | 0x80).

   Arrêts PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP
       [Les précisions sur ces types d'arrêts sont encore à documenter.]

   Commandes ptrace d'information et de redémarrage
       La  plupart  des   commandes   ptrace   (toutes   sauf   PTRACE_ATTACH,   PTRACE_SEIZE,   PTRACE_TRACEME,
       PTRACE_INTERRUPT  et  PTRACE_KILL)  nécessitent  que l'observé soit en arrêt-ptrace, sinon il échoue avec
       ESRCH.

       Quand l'observé est en arrêt-ptrace, l'observateur peut lire  et  écrire  les  donnés  sur  l'observé  en
       utilisant les commandes d'information. Ces commandes laissent l'observé en état arrêté-ptrace :

           ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);
           ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, long_val);
           ptrace(PTRACE_GETREGS/GETFPREGS, pid, 0, &struct);
           ptrace(PTRACE_SETREGS/SETFPREGS, pid, 0, &struct);
           ptrace(PTRACE_GETREGSET, pid, NT_foo, &iov);
           ptrace(PTRACE_SETREGSET, pid, NT_foo, &iov);
           ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo);
           ptrace(PTRACE_SETSIGINFO, pid, 0, &siginfo);
           ptrace(PTRACE_GETEVENTMSG, pid, 0, &long_var);
           ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);

       Remarquez  que  certaines  erreurs ne sont pas signalées. Par exemple, la configuration d'informations de
       signal (siginfo) pourrait être sans effet pour certains arrêts-ptrace, alors  que  l'appel  pourrait-être
       réussi  (en  renvoyant  0  et  sans définir errno) ; la demande de PTRACE_GETEVENTMSG pourrait réussir et
       renvoyer une quelconque valeur aléatoire si l'arrêt-ptrace actuel n'est pas documenté comme renvoyant  un
       message d'événement significatif.

       L'appel

           ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);

       ne  concerne qu'un observé. Les attributs actuels de l'observé sont remplacés. Les attributs sont hérités
       par les nouveaux observés créés et « attachés automatiquement » à  l'aide  d'options  PTRACE_O_TRACEFORK,
       PTRACE_O_TRACEVFORK ou PTRACE_O_TRACECLONE actives.

       Un autre groupe de commandes peut redémarrer l'observé arrêté ptrace. Ils sont de la forme :

           ptrace(cmd, pid, 0, sig);

       où   cmd  est PTRACE_CONT, PTRACE_LISTEN, PTRACE_DETACH, PTRACE_SYSCALL, PTRACE_SINGLESTEP, PTRACE_SYSEMU
       ou PTRACE_SYSEMU_SINGLESTEP. Si l'observé est en arrêt-distribution-signal, sig est le signal à  injecter
       (s'il  est  non  nul).  Sinon,  sig  pourrait  être  ignoré  (lors  du redémarrage d'un observé depuis un
       arrêt-ptrace différent d'un arrêt-distribution-signal, il est conseillé de toujours passer 0 à sig).

   Attachement et détachement
       Un thread peut être attaché à l'observateur en utilisant l'appel

           ptrace(PTRACE_ATTACH, pid, 0, 0);

       ou

           ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags);

       PTRACE_ATTACH envoie aussi SIGSTOP à ce thread. Si l'observateur veut que SIGSTOP  soit  sans  effet,  il
       doit  le  supprimer.  Remarquez  que  si  d'autres signaux sont envoyés en même temps à ce thread pendant
       l'attachement, l'observateur pourrait voir l'observé entrer en  arrêt-distribution-signal  avec  d'autres
       signaux d'abord ! Ces signaux sont d'habitude réinjectés jusqu'à ce que SIGSTOP soit vu, puis l'injection
       SIGSTOP est supprimée. Le bogue de conception ici est qu'un attachement ptrace et un  SIGSTOP  distribués
       en même temps peuvent entrer en compétition et le SIGSTOP risque d'être perdu.

       Puisque  l'attachement envoie SIGSTOP et que l'observateur le supprime normalement, cela risque de forcer
       le retour d'un EINTR perdu de l'appel système en cours d'exécution dans l'observé, tel que  c'est  décrit
       dans la section Injection et suppression de signal.

       Depuis  Linux 3.4,  PTRACE_SEIZE peut être utilisé à la place de PTRACE_ATTACH. PTRACE_SEIZE n'arrête pas
       le processus attaché. Si vous devez l'arrêter après attachement (ou à n'importe quel autre  moment)  sans
       lui envoyer de signal du tout, utilisez la commande PTRACE_INTERRUPT.

       La requête

           ptrace(PTRACE_TRACEME, 0, 0, 0);

       transforme  le thread appelant en observé. L'appel continue d'être exécuté (n'entre pas en arrêt-ptrace).
       PTRACE_TRACEME est habituellement suivi avec

           raise(SIGSTOP);

       et permet au père (qui est maintenant l'observateur) de respecter l'arrêt-distribution-signal.

       Si les options PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK ou PTRACE_O_TRACECLONE font effet, alors les  fils
       respectivement  créés  par vfork(2) ou clone(2) avec l'attribut CLONE_VFORK, vfork(2) ou clone(2) avec le
       signal de sortie configuré à SIGCHLD, et d'autres sortes de clone(2), sont  automatiquement  attachés  au
       même  observateur  qui  à  suivi  leur  père.  SIGSTOP  est  distribué  aux fils, les forçant à entrer en
       arrêt-distribution-signal après être sortis de l'appel système qu'ils ont créé.

       Le détachement de l'observé est réalisé par :

           ptrace(PTRACE_DETACH, pid, 0, sig);

       PTRACE_DETACH est une opération de redémarrage ; par conséquent elle  nécessite  que  l'observé  soit  en
       arrêt-ptrace.  Si  l'observé  est  en  arrêt-distribution-signal,  un signal peut être injecté. Sinon, le
       paramètre sig pourrait être silencieusement ignoré.

       Si l'observé est en cours d'exécution quand l'observateur veut le détacher, la  solution  habituelle  est
       d'envoyer  SIGSTOP  (en  utilisant  tgkill(2),  pour  s'assurer  qu'il  va au bon thread), d'attendre que
       l'observé s'arrête en arrêt-distribution-signal pour SIGSTOP et ensuite de  le  détacher  (en  supprimant
       l'injection   SIGSTOP).  Un  bogue  de  conception  est  que  l'observé  pourrait  entrer  dans  d'autres
       arrêts-ptrace et avoir besoin d'être redémarré et attendre encore, jusqu'à ce que SIGSTOP soit vu. Encore
       une  autre  complication  est  de  s'assurer  que l'observé n'est pas déjà arrêté-ptrace, parce qu'aucune
       distribution de signal n'arrive tant qu'il l'est — pas même SIGSTOP.

       Si l'observateur meurt, tous les observés sont automatiquement détachés et redémarrés, sauf s'il  étaient
       en arrêt-groupe. Le gestion de redémarrage depuis un arrêt-groupe est en ce moment dysfonctionnelle, mais
       le comportement « prévu » est de laisser les observés arrêtés et d'attendre un SIGCONT. Si l'observé  est
       redémarré depuis un arrêt-distribution-signal, le signal en attente est injecté.

   execve(2) sous ptrace
       Quand  un thread de processus multithreadé appelle execve(2), le noyau détruit tous les autres threads du
       processus, et réinitialise l'identifiant de thread du thread exécuté à l'identifiant de groupe de threads
       (PID)  (ou,  pour  le présenter autrement, quand un processus multithreadé fait un execve(2), à la fin de
       l'appel, il apparaît comme si l'execve(2) s'était appliqué au leader de groupe de threads,  quelque  soit
       le  thread  qui  a  fait  execve(2)).  Cette  réinitialisation de l'identifiant de thread semble est très
       déroutante pour les observateurs.

       *  Tous les autres threads s'arrêtent en arrêt PTRACE_EVENT_EXIT, si  l'option  PTRACE_O_TRACEEXIT  était
          activée.  Alors  tous les autres threads sauf le leader de groupe de threads signalent leur mort comme
          s'il s'étaient terminés par l'intermédiaire de _exit(2) avec un code de retour 0.

       *  L'observé en cours d'exécution modifie son identifiant de thread pendant qu'il  est  dans  l'execve(2)
          (rappelez-vous  que,  sous ptrace, le « pid » renvoyé par waitpid(2) ou fourni dans les appels ptrace,
          est  l'identifiant  de  thread  de  l'observé).  Ainsi,  l'identifiant  de  thread  de  l'observé  est
          réinitialisé  pour  être  le  même  que  son  identifiant  de  processus  (PID),  qui  est le même que
          l'identifiant de thread du leader de groupe de threads.

       *  Ensuite un arrêt PTRACE_EVENT_EXEC arrive, si l'option PTRACE_O_TRACEEXEC était activée.

       *  Si le leader de groupe de threads a signalé son arrêt PTRACE_EVENT_EXIT pendant ce temps, le leader de
          thread  mort  à  l'air  de  « revenir  de nulle part » du point de vue de l'observateur (remarque : le
          leader de groupe de threads ne signale pas sa mort à l'aide de WIFEXITED(status) tant qu'au  moins  un
          autre  thread  est  en  vie.  Cela  enlève  la  possibilité  à  l'observateur  de  le voir mourir puis
          réapparaître). Si le leader de groupe de threads était encore  en  vie,  cela  pourrait  être  vu  par
          l'observateur  comme si le leader de groupe revenait d'un autre appel système que celui dans lequel il
          était entré, ou même « revenait d'un appel système même s'il n'y avait pas d'appel  système ».  Si  le
          leader de groupe de threads n'était pas suivi (ou était suivi par un autre observateur), alors pendant
          execve(2) il apparaîtra comme s'il était devenu un observé de  l'observateur  de  l'observé  en  cours
          d'exécution.

       Tous les effets précédents sont des artifices de la modification d'identifiant de thread de l'observé.

       L'option PTRACE_O_TRACEEXEC est l'outil conseillé pour s'occuper de cette situation. D'abord, elle active
       l'arrêt PTRACE_EVENT_EXEC, qui arrive avant le retour d'execve(2). Dans  cet  arrêt,  l'observateur  peut
       utiliser   PTRACE_GETEVENTMSG   pour  récupérer  l'ancien  identifiant  de  thread  de  l'observé  (cette
       fonctionnalité a été introduite  avec  Linux 3.0).  Ensuite,  l'option  PTRACE_O_TRACEEXEC  désactive  la
       création obsolète de SIGTRAP dans execve(2).

       Quand  l'observé  reçoit une notification d'arrêt PTRACE_EVENT_EXEC, il est garanti qu'à part cet observé
       et le leader de groupe de threads, aucun autre thread du processus n'est en vie.

       Lors de la réception d'une notification d'arrêt PTRACE_EVENT_EXEC, l'observateur devrait nettoyer  toutes
       ses  structures  de  données  internes  décrivant  les  threads de ce processus et ne garder qu'une seule
       structure de données — celle qui décrit l'unique observé en cours d'exécution, avec

           identifiant de thread == identifiant de groupe de threads == identifiant de processus.

       Par exemple, soient deux threads qui appellent execve(2) en même temps :

       *** arrêt-entrée-appel-système obtenu dans le thread 1 : **
       PID1 execve("/bin/truc", "truc" <pas terminé…>
       *** PTRACE_SYSCALL émis pour le thread 1 **
       *** arrêt-entrée-appel-système obtenu dans le thread 2 : **
       PID2 execve("/bin/bidule", "bidule" <pas terminé…>
       *** PTRACE_SYSCALL émis pour le thread 2 **
       *** PTRACE_EVENT_EXEC obtenu pour PID0, PTRACE_SYSCALL émis **
       *** arrêt-sortie-appel-système obtenu pour PID0 : **
       PID0 <… retour d'execve> )             = 0

       Si l'option PTRACE_O_TRACEEXEC n'est  pas  effective  pour  l'observé  en  cours  d'exécution,  le  noyau
       distribue  un  SIGTRAP  supplémentaire  à  l'observé  après le retour d'execve(2). C'est un signal normal
       (similaire à celui  qui  peut  être  créé  par  kill  -TRAP),  pas  une  sorte  spéciale  d'arrêt-ptrace.
       L'utilisation  de  PTRACE_GETSIGINFO  pour  ce  signal renvoie si_code configuré à 0 (SI_USER). Ce signal
       pourrait être bloqué par un masque de signal, et pourrait ainsi être distribué (bien) plus tard.

       Normalement, l'observé (par exemple strace(1)) ne voudrait pas  montrer  ce  signal  SIGTRAP  post-execve
       supplémentaire  à  l'utilisateur,  et  voudrait  supprimer  sa  distribution  à l'observé (si SIGTRAP est
       configuré à SIG_DFL, s'est un signal tueur). Cependant, déterminer quel est le SIGTRAP à supprimer  n'est
       pas  simple.  La configuration de l'option PTRACE_O_TRACEEXEC et par conséquent la suppression du SIGTRAP
       supplémentaire est l'approche conseillée.

   Vrai père
       L'interface de programmation de ptrace utilise (parfois mal) la norme UNIX de signalement de père ou fils
       par  l'intermédiaire  de  waitpid(2).  Cela  a régulièrement forcé le vrai père du processus à arrêter de
       recevoir plusieurs sortes de notifications de waitpid(2) quand le processus fils est suivi par  un  autre
       processus.

       Nombreux  bogues  de  ce  type  ont  été  corrigés,  mais  il en reste encore beaucoup dans Linux 2.6.38.
       Consultez la section BOGUES ci dessous.

       Depuis Linux 2.6.38, ce qui suit est censé fonctionner correctement :

       *  l'exécution ou la mort par signal sont d'abord signalées à l'observateur,  puis,  quand  l'observateur
          consomme  le  résultat  de  waitpid(2),  au  vrai  père (au vrai père seulement quand l'intégralité du
          processus multithreadé se termine). Si l'observateur et le  vrai  père  sont  le  même  processus,  le
          signalement n'est envoyé qu'une fois.

VALEUR RENVOYÉE

       En cas de succès, la requête PTRACE_PEEK* renvoie les données demandées (mais consultez les NOTES), alors
       que les autres requêtes renvoient zéro.

       ptrace() renvoie -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, l'appelant doit effacer errno avant l'appel, et
       ensuite le vérifier pour savoir si une erreur s'est produite.

ERREURS

       EBUSY  (i386 seulement) Une erreur est survenue 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 non valable de l'observateur ou de l'observé,
              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 non valable.

       EIO    La  requête  request n'est pas valable ou une tentative de lecture ou d'écriture dans une zone non
              valable de mémoire de l'observateur ou de l'observé a eu lieu. Un problème d'alignement a aussi pu
              survenir  sur  une  frontière  de  mot,  ou une tentative de redémarrage en envoyant un signal non
              valable.

       EPERM  Le processus indiqué ne peut pas être suivi. Cela peut  être  dû  à  un  manque  de  privilège  de
              l'observateur  (la  capacité  nécessaire  est  CAP_SYS_PTRACE).  Les  processus non privilégiés 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 (sur les noyaux
              antérieurs à 2.6.26) être init(8) (le processus numéro 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 ont besoin d'un observé arrêté).

CONFORMITÉ

       SVr4, BSD 4.3.

NOTES

       Bien  que  les  arguments  de  ptrace() soient interprétés comme dans le prototype donné, la bibliothèque
       glibc déclare ptrace comme une fonction variadique où seul l'argument request est corrigé. Il vaut  mieux
       toujours  fournir  quatre  arguments, même si l'opération demandée ne les utilise pas, en configurant les
       arguments non utilisés ou ignorés à 0L ou (void *) 0.

       L'interface de programmation de l'appel  système  est  différente  pour  les  requêtes   PTRACE_PEEKTEXT,
       PTRACE_PEEKDATA  et  PTRACE_PEEKUSER :  elles  stockent le résultat à l’adresse indiquée par le paramètre
       data, et la valeur de retour est l’attribut d’erreur. La fonction glibc encapsulant cet appel fournit une
       interface détaillée dans la section DESCRIPTION ci-dessus, et le résultat qu'elle renvoie est le résultat
       de l'appel système.

       Dans les noyaux antérieurs à 2.6.26, 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).

       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.

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 des en-têtes  du  noyau 2.6
       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.

       Les notifications d'arrêt-groupe sont envoyées à l'observateur, mais pas au  vrai  père.  C'était  encore
       vrai en 2.6.38.6.

       Si  un  leader  de groupe de threads est suivi et existe en appelant _exit(2), un arrêt PTRACE_EVENT_EXIT
       lui arrivera (si réclamé), mais la notification WIFEXITED suivante ne sera pas distribuée avant la fin de
       tous les autres threads. Comme expliqué précédemment, si un des autres threads appelle execve(2), la mort
       du leader de groupe de threads ne sera jamais signalée. Si le thread exécuté  n'est  pas  suivi  par  cet
       observateur,  l'observé  ne  saura  jamais  qu'execve(2)  est  arrivé.  Un  contournement possible est de
       PTRACE_DETACHer le leader de groupe de threads au lieu de le redémarrer dans ce cas. C'était encore  vrai
       en 2.6.38.6.

       Un  signal  SIGKILL  pourrait  encore  provoquer  un  arrêt PTRACE_EVENT_EXIT avant une véritable mort du
       signal. Cela pourrait évoluer à l'avenir. SIGKILL est supposé tuer immédiatement  les  tâches  même  sous
       ptrace. C'était encore vrai en 2.6.38.6.

       Certains appels système renvoient EINTR si un signal a été envoyé à l'observé, mais que la distribution a
       été supprimée par l'observateur (c'est une opération tout à fait caractéristique : elle  est  normalement
       réalisée  par les débogueurs sur tous les attachements, afin de ne pas introduire de SIGSTOP défectueux).
       Depuis Linux 3.2.9, les appels système suivants sont concernés (cette liste est sans doute  incomplète) :
       epoll_wait(2)  et  read(2) depuis un descripteur de fichier inotify(7). Le symptôme classique de ce bogue
       est qu'en attachant à un processus quiescent avec la commande

           strace -p <ID-processus>

       alors, au lieu de la ligne de sortie habituelle attendue comme

           restart_syscall(<... retour de l'appel interrompu ...>_

       ou

           select(6, [5], NULL, [5], NULL_

       (« _ » indique la position du curseur), plusieurs lignes sont affichées. Par exemple :

           clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0
           epoll_wait(4,_

       Ce qui n'est pas visible ici est que le processus a été bloqué dans epoll_wait(2) avant que strace(1)  ne
       s'y  soit  attaché. L'attachement a forcé epoll_wait(2) à revenir dans l'espace utilisateur avec l'erreur
       EINTR. Dans ce cas particulier, le programme a réagit  à  EINTR  en  vérifiant  l'heure  actuelle  et  en
       exécutant  encore  epoll_wait(2)  (les  programmes  qui  ne  s'attendent  pas  à  de telles erreurs EINTR
       « perdue » risquent de se comporter de façon inattendue sur une attache strace(1)).

VOIR AUSSI

       gdb(1),  strace(1),  clone(2),  execve(2),  fork(2),  gettid(2),   sigaction(2),   tgkill(2),   vfork(2),
       waitpid(2), exec(3), capabilities(7), signal(7)

COLOPHON

       Cette page fait partie de la publication 3.65 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

       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par
       l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.

       Christophe      Blaess      <http://www.blaess.fr/christophe/>      (1996-2003),       Alain       Portal
       <http://manpagesfr.free.fr/>  (2003-2006).  Julien  Cristau  et  l'équipe  francophone  de  traduction de
       Debian (2006-2009).

       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> ».