.\" -*- coding: UTF-8 -*- .\" Copyright (c) 1993 Michael Haardt .\" Fri Apr 2 11:32:09 MET DST 1993 .\" .\" and changes Copyright (C) 1999 Mike Coleman (mkc@acm.org) .\" -- major revision to fully document ptrace semantics per recent Linux .\" kernel (2.2.10) and glibc (2.1.2) .\" Sun Nov 7 03:18:35 CST 1999 .\" .\" and Copyright (c) 2011, Denys Vlasenko .\" .\" %%%LICENSE_START(GPLv2+_DOC_FULL) .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, see .\" . .\" %%%LICENSE_END .\" .\" Modified Fri Jul 23 23:47:18 1993 by Rik Faith .\" Modified Fri Jan 31 16:46:30 1997 by Eric S. Raymond .\" Modified Thu Oct 7 17:28:49 1999 by Andries Brouwer .\" Modified, 27 May 2004, Michael Kerrisk .\" Added notes on capability requirements .\" .\" 2006-03-24, Chuck Ebbert <76306.1226@compuserve.com> .\" Added PTRACE_SETOPTIONS, PTRACE_GETEVENTMSG, PTRACE_GETSIGINFO, .\" PTRACE_SETSIGINFO, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP .\" (Thanks to Blaisorblade, Daniel Jacobowitz and others who helped.) .\" 2011-09, major update by Denys Vlasenko .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH PTRACE 2 "19. August 2014" Linux Linux\-Programmierhandbuch .SH BEZEICHNUNG ptrace \- Prozessverfolgung .SH ÜBERSICHT .nf \fB#include \fP .sp \fBlong ptrace(enum __ptrace_request \fP\fIAnfrage\fP\fB, pid_t \fP\fIPid\fP\fB, \fP \fB void *\fP\fIAdresse\fP\fB, void *\fP\fIDaten\fP\fB);\fP .fi .SH BESCHREIBUNG Der Systemaufruf \fBptrace\fP() stellt ein Mittel bereit, wodurch ein Prozess (der »Verfolger«) die Ausführung eines anderen Prozesses (des »verfolgten Prozesses«) beobachten und steuern kann und seinen Speicher sowie die Register untersuchen und ändern kann. Er wird in erster Linie benutzt, um Fehlersuche mittels Haltepunkten zu implementieren und Systemaufrufe zu verfolgen. .LP Ein verfolgter Prozess muss zuerst an den Verfolger angehängt werden. Anhängen und nachfolgende Befehle bestehen pro Thread: In einem Prozess mit mehreren Threads kann jeder Thread individuell an einen (möglicherweise unterschiedlichen) Verfolger angehängt werden oder nicht angehängt und folglich nicht auf Fehler untersucht werden. Daher bedeutet »verfolgter Prozess« immer »(ein) Thread«, niemals »ein Prozess (mit möglicherweise mehreren Threads)«. Ptrace\-Befehle werden immer an einen bestimmten verfolgten Prozess gesandt. Der Aufruf hat folgende Form: ptrace(PTRACE_foo, PID, …) wobei \fIPID\fP die Thread\-Kennung des zugehörigen Linux\-Threads ist. .LP (Beachten Sie, dass auf dieser Seite ein »Prozess aus mehreren Threads« eine Thread\-Gruppe bezeichnet, die aus Threads besteht, die mittels des \fBclone\fP(2)\-Schalters \fBCLONE_THREAD\fP erzeugt wurde.) .LP Ein Prozess kann eine Verfolgung mittels \fBfork\fP(2) starten und als Ergebnis einen Kindprozess erhalten, der \fBPTRACE_TRACEME\fP ausführt, was (üblicherweise) von einem \fBexecve\fP(2) gefolgt wird. Alternativ kann ein Prozess die Verfolgung eines anderen Prozesses mittels \fBPTRACE_ATTACH\fP oder \fBPTRACE_SEIZE\fP beginnen. .LP Während der Prozess verfolgt wird, wird er jedesmal stoppen, wenn ein Signal gesandt wird, sogar wenn das Signal ignoriert wird. (Eine Ausnahme ist \fBSIGKILL\fP, das seine normale Wirkung erzielt.) Der Verfolger wird bei seinem nächsten Aufruf von \fBwaitpid\fP(2) (oder den zugehörigen »wait«\-Systemaufrufen) benachrichtigt; dies wird einen \fIStatus\fPwert zurückgeben, der Informationen enthält, die den Grund angeben, weshalb der verfolgte Prozess stoppte. Während der verfolgte Prozess angehalten ist, kann der Verfolger verschiedene Ptrace\-Anfragen verwenden, um den verfolgten Prozess zu untersuchen und zu verändern. Dann veranlasst der Verfolger den verfolgten Prozess fortzufahren und wahlweise das versandte Signal zu ignorieren (oder stattdessen sogar ein anderes Signal zu senden). .LP Falls die Option \fBPTRACE_O_TRACEEXEC\fP nicht in Kraft ist, werden alle erfolgreichen Aufrufe von \fBexecve\fP(2) durch den verfolgten Prozess zum Senden eines \fBSIGTRAP\fP\-Signals veranlassen, um dem Elternprozess die Möglichkeit zu geben, die Kontrolle zu erlangen, bevor die Ausführung des neuen Programms beginnt. .LP Wenn der Verfolger die Verfolgung beendet hat, kann er veranlassenden, das der verfolgte Prozess mit \fBPTRACE_DETACH\fP in einem normal Modus ohne Verfolgung fortfährt. .LP Der Wert des Arguments \fIAnfrage\fP legt die Aktion des Systemaufrufs fest: .TP \fBPTRACE_TRACEME\fP zeigt an, dass dieser Prozess durch seinen Elternprozess verfolgt wird. Ein Prozess sollte diese Anfrage wahrscheinlich nicht stellen, falls sein Elternprozess nicht erwartet, ihn zu verfolgen.(\fIPID\fP, \fIAdresse\fP und \fIDaten\fP werden ignoriert.) .IP Die \fBPTRACE_TRACEME\fP\-Anfrage wird nur vom verfolgten Prozess benutzt; die verbleibenden Anfragen werden nur vom verfolgenden Prozess benutzt. In den folgenden Anfragen gibt \fIPID\fP die Thread\-Kennung des verfolgten Prozesses an, der beeinflusst werden soll. Für andere Anfragen als \fBPTRACE_ATTACH\fP, \fBPTRACE_SEIZE\fP, \fBPTRACE_INTERRUPT\fP und \fBPTRACE_KILL\fP muss der verfolgte Prozess gestoppt werden. .TP \fBPTRACE_PEEKTEXT\fP, \fBPTRACE_PEEKDATA\fP liest ein »word« an der Stelle \fIAdresse\fP im Speicher des verfolgten Prozesses und gibt das »word« als Ergebnis des \fBptrace\fP()\-Aufrufs zurück. Linux hat keine separaten Adressräume für Text und Daten, daher sind diese beiden Anfragen derzeit gleichwertig. (Das Argument \fIDaten\fP wird ignoriert, lesen Sie aber auch ANMERKUNGEN.) .TP \fBPTRACE_PEEKUSER\fP .\" PTRACE_PEEKUSR in kernel source, but glibc uses PTRACE_PEEKUSER, .\" and that is the name that seems common on other systems. Liest ein »word« bei Versatz \fIAdresse\fP im BENUTZERbereich des verfolgten Prozesses, der die Register und andere Informationen über den Prozess enthält (siehe \fI\fP). Das »word« wird als Ergebnis des \fBptrace\fP()\-Aufrufs zurückgegeben. Typischerweise muss der Versatz am »word« ausgerichtet sein, obwohl dies je nach Architektur variieren kann. Lesen Sie die ANMERKUNGEN. (\fIDaten\fP wird ignoriert, lesen Sie aber auch ANMERKUNGEN.) .TP \fBPTRACE_POKETEXT\fP, \fBPTRACE_POKEDATA\fP kopiert das »word« \fIDaten\fP an die Stelle \fIAdresse\fP im Speicher des verfolgenden Prozesses. Wie bei \fBPTRACE_PEEKTEXT\fP und \fBPTRACE_PEEKDATA\fP sind die beiden Anfragen derzeit gleichwertig. .TP \fBPTRACE_POKEUSER\fP .\" PTRACE_POKEUSR in kernel source, but glibc uses PTRACE_POKEUSER, .\" and that is the name that seems common on other systems. .\" FIXME In the preceding sentence, which modifications are disallowed, .\" and when they are disallowed, how does user space discover that fact? kopiert das »word« \fIDaten\fP an den Versatz \fIAdresse\fP im BENUTZERbereich des verfolgten Prozesses. Wie für \fBPTRACE_PEEKUSER\fP muss der Versatz am »word« ausgerichtet sein. Um die Integrität des Kernels aufrecht zu erhalten, sind einige Änderungen in BENUTZERbereich nicht erlaubt. .TP \fBPTRACE_GETREGS\fP, \fBPTRACE_GETFPREGS\fP kopiert die Mehrzweck\- beziehungsweise Fließpunktregister des verfolgten Prozesses an die Stelle \fIDaten\fP im Verfolger. Lesen Sie \fI\fP, um Informationen über das Format dieser Daten zu erhalten. (\fIAdresse\fP wird ignoriert.) Beachten Sie, dass auf SPARC\-Systemen die Bedeutung von \fIDaten\fP und \fIAdresse\fP umgekehrt ist; daher wird \fIDaten\fP ignoriert und die Register werden an die Adresse \fIAdresse\fP kopiert. \fBPTRACE_GETREGS\fP und \fBPTRACE_GETFPREGS\fP sind nicht auf allen Architekturen verfügbar. .TP \fBPTRACE_GETREGSET\fP (seit Linux 2.6.34) liest die Register des verfolgten Prozesses. \fIAdresse\fP gibt auf eine von der Architektur unabhängige Weise den Typ des Registers an, das gelesen werden soll. \fBNT_PRSTATUS\fP (mit numerischem Wert 1) führt normalerweise dazu, dass Allzweckregister gelesen werden. Falls die CPU zum Beispiel Fließkomma\- und/oder Vektorregister hat, können sie durch Setzen von \fIAdresse\fP auf die entsprechende Konstante \fBNT_foo\fP ermittelt werden. \fIDaten\fP zeigt auf einen \fBstruct iovec\fP, der den Speicherort und die Länge des Zielpuffers beschreibt. Bei der Rückkehr ändert der Kernel \fBiov.len\fP, um die tatsächliche Anzahl zurückgegebener Byte anzuzeigen. .TP \fBPTRACE_SETREGS\fP, \fBPTRACE_SETFPREGS\fP .\" FIXME . In the preceding sentence, which modifications are disallowed, .\" and when they are disallowed, how does user space discover that fact? verändert die Mehrzweck\- beziehungsweise Fließpunktregister des verfolgten Prozesses von der Adresse \fIDaten\fP im Verfolger. Wie für \fBPTRACE_POKEUSER\fP können einige Änderungen am Mehrzweckregister verboten sein. (\fIAdresse\fP wird ignoriert.) Beachten Sie, dass auf SPARC\-Systemen die Bedeutung von \fIDaten\fP und \fIAdresse\fP umgekehrt ist; daher wird \fIDaten\fP ignoriert und die Register werden von der Adresse \fIAdresse\fP kopiert. \fBPTRACE_SETREGS\fP und \fBPTRACE_SETFPREGS\fP sind nicht auf allen Architekturen verfügbar. .TP \fBPTRACE_SETREGSET\fP (seit Linux 2.6.34) verändert die Register des verfolgten Prozesses. Die Bedeutung von \fIAdresse\fP und \fIDaten\fP ist analog zu \fBPTRACE_GETREGSET\fP. .TP \fBPTRACE_GETSIGINFO\fP (seit Linux 2.3.99\-pre6) ruft Informationen über das Signal ab, das den Stopp verursachte. Kopiert eine \fIsiginfo_t\fP\-Struktur (siehe \fBsigaction\fP(2)) vom verfolgten Prozess an die Stelle \fIDaten\fP im Verfolger. (\fIAdresse\fP wird ignoriert.) .TP \fBPTRACE_SETSIGINFO\fP (seit Linux 2.3.99\-pre6) setzt Signalinformationen: kopiert eine \fIsiginfo_t\fP\-Struktur von der Adresse \fIDaten\fP vom verfolgenden zum verfolgten Prozess. Dies wird nur Signale betreffen, die normalerweise an den verfolgten Prozess zugestellt würden und vom Verfolger abgefangen wurden. Es könnte schwierig werden, diese normalen Signale von künstlichen Signalen zu unterscheiden, die von \fBptrace\fP() selbst generiert wurden. (\fIAdresse\fP wird ignoriert.) .TP \fBPTRACE_PEEKSIGINFO\fP (seit Linux 3.10) .\" commit 84c751bd4aebbaae995fe32279d3dba48327bad4 fragt \fIsiginfo_t\fP\-Strukturen ab, ohne Signale aus einer Warteschlange zu entfernen. \fIAdresse\fP zeigt auf eine \fIptrace_peeksiginfo_args\fP\-Struktur, die die Ordnungsposition angibt, von der das Kopieren der Signale starten soll sowie die Anzahl zu kopierender Signale. \fIsiginfo_t\fP\-Strukturen werden in den Puffer kopiert, auf den \fIDaten\fP verweist. Der Rückgabewert enthält die Anzahl der kopierten Signale (null zeigt an, dass es an der angegebenen Ordnungsposition kein entsprechendes Signal gibt). Innerhalb der zurückgegebenen \fIsiginfo\fP\-Strukturen enthält das Feld \fIsi_code\fP Informationen (\fB__SI_CHLD\fP, \fB__SI_FAULT\fP, etc.), die ansonsten nicht an den Userspace offengelegt werden. .PP .in +10n .nf struct ptrace_peeksiginfo_args { u64 off; /* Ordnungsposition in der Warteschlange, an der mit dem Kopieren der Signale begonnen wird */ u32 flags; /* PTRACE_PEEKSIGINFO_SHARED oder 0 */ s32 nr; /* Anzahl zu kopierender Signale */ }; .fi Derzeit gibt es nur einen Schalter, \fBPTRACE_PEEKSIGINFO_SHARED\fP, um Signale aus der prozessweiten Signalwarteschlange auszugeben. Falls dieser Schalter nicht gesetzt ist, werden Signale von der Tread\-eigenen Warteschlange des angegebenen Threads gelesen. .in .PP .TP \fBPTRACE_GETSIGMASK\fP (seit Linux 3.11) .\" commit 29000caecbe87b6b66f144f72111f0d02fbbf0c1 Platzieren Sie eine Kopie der Maske blockierter Signale (siehe \fBsigprocmask\fP(2)) in den Puffer, auf den \fIDaten\fP zeigt. Dies sollte ein Zeiger auf einen Puffer des Typs \fIsigset_t\fP sein. Das Argument \fIAdresse\fP enthält die Größe des Puffers, auf den \fIDaten\fP zeigt (d.h. \fIsizeof(sigset_t)\fP). .TP \fBPTRACE_SETSIGMASK\fP (seit Linux 3.11) ändert die Maske blockierter Signale (siehe \fBsigprocmask\fP(2)) auf den Wert, der im Puffer angegeben wird, auf den \fIDaten\fP zeigt. Dies sollte ein Zeiger auf einen Puffer des Typs \fIsigset_t\fP sein. Das Argument \fIAdresse\fP enthält die Größe des Puffers, auf den \fIDaten\fP zeigt (d.h. \fIsizeof(sigset_t)\fP). .TP \fBPTRACE_SETOPTIONS\fP (seit Linux 2.4.6; siehe FEHLER für Vorsichtsmaßnahmen) setzt Ptrace\-Optionen von \fIDaten\fP. (\fIAdresse\fP wird ignoriert.) \fIDaten\fP wird als Bit in der Maske der Optionen interpretiert, die durch die folgenden Schalter angegeben wird: .RS .TP \fBPTRACE_O_EXITKILL\fP (seit Linux 3.8) .\" commit 992fb6e170639b0849bace8e49bf31bd37c4123 falls ein verfolgender Prozess diesen Schalter setzt, wird an jeden verfolgten Prozess ein \fBSIGKILL\fP\-Signal geschickt, falls der verfolgende Prozess beendet wird. Diese Option ist für diejenigen nützlich, die Ptrace einsperren und sicherstellen wollen, dass der verfolgte Prozess nie der Steuerung des verfolgenden Prozesses entkommt. .TP \fBPTRACE_O_TRACECLONE\fP (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nächsten Aufruf von \fBclone\fP(2) und startet automatisch die Verfolgung des neu geklonten Prozesses, der mit einem \fBSIGSTOP\fP oder, falls \fBPTRACE_SEIZE\fP benutzt wurde, mit \fBPTRACE_EVENT_STOP\fP starten wird. Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)) .fi Die PID des neuen Prozesses kann mit \fBPTRACE_GETEVENTMSG\fP abgefragt werden. .IP Diese Option kann nicht in allen Fällen \fBclone\fP(2)\-Aufrufe abfangen. Falls der verfolgte Prozess \fBclone\fP(2) mit dem Schalter \fBCLONE_VFORK\fP aufruft, wird stattdessen \fBPTRACE_EVENT_VFORK\fP geschickt, wenn \fBPTRACE_O_TRACEVFORK\fP gesetzt ist; andernfalls wird \fBPTRACE_EVENT_FORK\fP geschickt, wenn der verfolgte Prozess \fBclone\fP(2) mit dem auf \fBSIGCHLD\fP gesetzten Beendigungssignal aufgerufen wird, falls \fBPTRACE_O_TRACEFORK\fP gesetzt ist. .TP \fBPTRACE_O_TRACEEXEC\fP (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nächsten \fBexecve\fP(2). Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8)) .fi Falls der ausführende Thread kein führender Thread der Gruppe ist, wird die Thread\-Kennung vor dem Stopp auf die Kennung des führenden Threads der Gruppe zurückgesetzt. Seit Linux 3.0 kann die vorherige Thread\-Kennung mit \fBPTRACE_GETEVENTMSG\fP abgefragt werden. .TP \fBPTRACE_O_TRACEEXIT\fP (seit Linux 2.5.60) stoppt den verfolgten Prozess beim Beenden. Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8)) .fi Der Exit\-Status des verfolgten Prozesses kann mit \fBPTRACE_GETEVENTMSG\fP abgefragt werden. .IP Der verfolgte Prozess wird frühzeitig während des Beendens gestoppt, wenn die Register noch verfügbar sind, was es dem Verfolger ermöglicht, zu sehen, wo das Beenden veranlasst wurde, wohingegen die normale Benachrichtigung über die Beendigung geschickt wird, wenn der Prozess das Beenden abgeschlossen hat. Auch wenn der Kontext verfügbar ist, kann der Verfolger das Beenden an diesem Punkt nicht mehr verhindern. .TP \fBPTRACE_O_TRACEFORK\fP (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nächsten Aufruf von \fBfork\fP(2) und startet die Verfolgung des neuen Prozesszweiges, der mit einem \fBSIGSTOP\fP oder, falls \fBPTRACE_SEIZE\fP benutzt wurde, mit \fBPTRACE_EVENT_STOP\fP starten wird. Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8)) .fi Die PID des neuen Prozesses kann mit \fBPTRACE_GETEVENTMSG\fP abgefragt werden. .TP \fBPTRACE_O_TRACESYSGOOD\fP (seit Linux 2.4.6) Wenn Systemaufrufe abgefangen werden, wird Bit 7 in der Signalnummer gesetzt (d.h. \fISIGTRAP | 0x80\fP geschickt). Dies erleichtert es dem Verfolger, den Unterschied zwischen normalen, abgefangenen Signalen und denen, die durch einen Systemaufruf verursacht wurden, mitzuteilen. (\fBPTRACE_O_TRACESYSGOOD\fP funktioniert möglicherweise nicht auf allen Architekturen.) .TP \fBPTRACE_O_TRACEVFORK\fP (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nächsten Aufruf von \fBvfork\fP(2) und startet automatisch die Verfolgung des neuen »vfork«\-Prozesszweiges, der mit einem \fBSIGSTOP\fP oder, falls \fBPTRACE_SEIZE\fP benutzt wurde, mit \fBPTRACE_EVENT_STOP\fP starten wird. Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8)) .fi Die PID des neuen Prozesses kann mit \fBPTRACE_GETEVENTMSG\fP abgefragt werden. .TP \fBPTRACE_O_TRACEVFORKDONE\fP (seit Linux 2.5.60) stoppt den verfolgten Prozess bei Vollendung des nächsten \fBvfork\fP(2). Ein \fBwaitpid\fP(2) durch den Verfolger wird einen \fIStatus\fPwert wie diesen zurückgeben: .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8)) .fi Die PID des neuen Prozesses kann (seit Linux 2.6.18) abgefragt werden mit .RE .TP \fBPTRACE_GETEVENTMSG\fP (seit Linux 2.5.46) eine Nachricht (als \fIunsigned long\fP) über das Ptrace\-Ereignis abfragen, das einfach so auftrat und es an die Adresse \fIDaten\fP im Verfolger platzieren. Für \fBPTRACE_EVENT_EXIT\fP ist dies der Exit\-Status des verfolgten Prozesses. Für \fBPTRACE_EVENT_FORK\fP, \fBPTRACE_EVENT_VFORK\fP und \fBPTRACE_EVENT_CLONE\fP ist dies die PID des neuen Prozesses. (\fIAdresse\fP wird ignoriert.) .TP \fBPTRACE_CONT\fP startet den gestoppten, verfolgten Prozess erneut. Falls \fIDaten\fP nicht Null ist, wird es als Nummer des Signals interpretiert, das an den verfolgten Prozess geschickt wird; andernfalls wird kein Signal geschickt. Dadurch kann der Verfolger zum Beispiel steuern, ob ein Signal an den verfolgten Prozess geschickt wird oder nicht. (\fIAdresse\fP wird ignoriert.) .TP \fBPTRACE_SYSCALL\fP, \fBPTRACE_SINGLESTEP\fP startet den gestoppten, verfolgten Prozess wie für \fBPTRACE_CONT\fP, arrangiert aber, dass der verfolgte Prozess beim nächsten Eintritt oder einem Systemaufruf beziehungsweise nach der Ausführung einer einzelnen Anweisung gestoppt wird. (Der verfolgte Prozess wird auch, wie üblich, über den Empfang des Signals gestoppt.) Aus der Sicht des Verfolgers scheint es, als ob der verfolgte Prozess durch Empfang eines \fBSIGTRAP\fP gestoppt wurde. Daher gibt es zum Beispiel für \fBPTRACE_SYSCALL\fP die Idee, beim ersten Stopp die Argumente des Systemaufrufs zu prüfen, dann einen anderen \fBPTRACE_SYSCALL\fP zu schicken und den Rückgabewert des Systemaufrufs am zweiten Stopp zu prüfen. Das Argument \fIDaten\fP wird wie für \fBPTRACE_CONT\fP behandelt. (\fIAdresse\fP wird ignoriert.) .TP \fBPTRACE_SYSEMU\fP, \fBPTRACE_SYSEMU_SINGLESTEP\fP (seit Linux 2.6.14) .\" As at 3.7 für \fBPTRACE_SYSEMU\fP beim nächsten Eintritt für den Systemaufruf, der nicht ausgeführt wird, fortfahren und stoppen; für \fBPTRACE_SYSEMU_SINGLESTEP\fP das gleiche tun, aber in einem einzigen Schritt, wenn es sich nicht um einen Systemaufruf handelt. Dieser Aufruf wird von Programmen wie »User Mode Linux« verwandt, die die Systemaufrufe des verfolgten Prozesses emulieren wollen. Das Argument \fIDaten\fP wird wie für \fBPTRACE_CONT\fP behandelt. Das Argument \fIAdresse\fP wird ignoriert. Diese Anfragen werden derzeit nur unter x86 unterstützt. .TP \fBPTRACE_LISTEN\fP (seit Linux 3.4) startet den gestoppten verfolgten Prozess erneut, verhindert jedoch seine Ausführung. Der resultierende Status ist dem eines Prozesses ähnlich, der durch ein \fBSIGSTOP\fP (oder ein anderes Stoppsignal) angehalten wurde. Zusätzliche Informationen finden Sie im Unterabschnitt »Gruppenstopp«. \fBPTRACE_LISTEN\fP funktioniert nur bei verfolgten Prozessen, die durch \fBPTRACE_SEIZE\fP angehängt wurden. .TP \fBPTRACE_KILL\fP sendet dem verfolgten Prozess ein \fBSIGKILL\fP, um ihn zu beenden. (\fIAdresse\fP und \fIDaten\fP werden ignoriert.) .IP .\" [Note from Denys Vlasenko: .\" deprecation suggested by Oleg Nesterov. He prefers to deprecate it .\" instead of describing (and needing to support) PTRACE_KILL's quirks.] \fIDiese Transaktion ist überholt; benutzen Sie sie nicht!\fP Senden Sie stattdessen ein \fBSIGKILL\fP direkt mittels \fBkill\fP(2) oder \fBtgkill\fP(2). Das Problem bei \fBPTRACE_KILL\fP ist, dass es verlangt, dass sich der verfolgte Prozess in eine Signallieferstopp befindet, andernfalls funktioniert es möglicherweise nicht (d.h. es könnte komplett erfolgreich sein, würde aber den verfolgten Prozess killen). Im Gegensatz dazu hat das direkte Senden von einem \fBSIGKILL\fP keine derartige Beschränkung. .TP \fBPTRACE_INTERRUPT\fP (seit Linux 3.4) stoppt einen verfolgten Prozess. Falls der verfolgte Prozess im Kernel\-Space läuft oder schläft und \fBPTRACE_SYSCALL\fP in Kraft ist, wird der Systemaufruf unterbrochen und »syscall\-exit\-stop« gemeldet. (Der unterbrochene Systemaufruf wird beim Neustart des verfolgten Prozesses ebenfalls neu gestartet.) Falls der verfolgte Prozess bereits durch ein Signal gestoppt und \fBPTRACE_LISTEN\fP an ihn gesendet wurde, stoppt der verfolgte Prozess mit \fBPTRACE_EVENT_STOP\fP und \fIWSTOPSIG(Status)\fP gibt das Stoppsignal zurück. Falls zur selben Zeit irgendein anderes »ptrace\-stop« erzeugt wird (zum Beispiel, weil ein Signal an den verfolgten Prozess gesendet wird), tritt dieses »ptrace\-stop« auf. Falls nichts von obigem zutrifft (zum Beispiel, weil der verfolgte Prozess im Userspace läuft), stoppt er mit \fBPTRACE_EVENT_STOP\fP mit \fIWSTOPSIG(status)\fP == \fBSIGTRAP\fP. \fBPTRACE_INTERRUPT\fP funktioniert nur bei verfolgten Prozessen, die durch \fBPTRACE_SEIZE\fP angehängt wurden. .TP \fBPTRACE_ATTACH\fP .\" No longer true (removed by Denys Vlasenko, 2011, who remarks: .\" "I think it isn't true in non-ancient 2.4 and in 2.6/3.x. .\" Basically, it's not true for any Linux in practical use. .\" ; the behavior of the tracee is as if it had done a .\" .BR PTRACE_TRACEME . .\" The calling process actually becomes the parent of the tracee .\" process for most purposes (e.g., it will receive .\" notification of tracee events and appears in .\" .BR ps (1) .\" output as the tracee's parent), but a .\" .BR getppid (2) .\" by the tracee will still return the PID of the original parent. hängt an den Prozess, der durch \fIPID\fP angegeben wird, an, lässt ihn zum verfolgten Prozess des aufrufenden Prozesses werden. Dem verfolgten Prozess wird ein \fBSIGSTOP\fP gesandt, er wird aber nicht notwendigerweise durch die Vollendung dieses Aufrufs gestoppt; benutzen Sie \fBwaitpid\fP(2), um auf das Stoppen des verfolgten Prozesses zu warten. Lesen Sie den Unterabschnitt »Anhängen und Loslösen«, um zusätzliche Informationen zu erhalten. (\fIAdresse\fP und \fIDaten\fP werden ignoriert.) .TP \fBPTRACE_SEIZE\fP (seit Linux 3.4) hängt an den durch \fIPID\fP angegebenen Prozess an und macht ihn zu einem verfolgten Prozess des aufrufenden Prozesses. Im Gegensatz zu \fBPTRACE_ATTACH\fP stoppt \fBPTRACE_SEIZE\fP den Prozess nicht. Nur ein mit \fBPTRACE_SEIZE\fP angehängter Prozess kann \fBPTRACE_INTERRUPT\fP\- und \fBPTRACE_LISTEN\fP\-Befehle entgegennehmen. \fIAdresse\fP muss Null sein. \fIDaten\fP enthält eine Bitmaske von Ptrace\-Optionen, die sofort aktiviert werden. .TP \fBPTRACE_DETACH\fP startet den gestoppten, verfolgten Prozess wie für \fBPTRACE_CONT\fP, löst ihn aber zuerst vom Prozess ab. Unter Linux kann ein verfolgter Prozess auf diese Art abgelöst werden, ohne Rücksicht darauf zu nehmen, welche Methode zum Starten der Verfolgung benutzt wurde.(\fIAdresse\fP wird ignoriert.) .SS "Tod unter Ptrace" Wenn ein Prozess (der möglicherweise aus mehreren Threads besteht) ein killendes Signal erhält (eines, dessen Einstellung auf \fBSIG_DFL\fP gesetzt ist und dessen Standardaktion das Killen des Prozesses ist) werden alle Threads beendet. Verfolgte Prozesse melden ihren Tod an ihre(n) Verfolger. Die Benachrichtigung über dieses Ereignis wird über \fBwaitpid\fP(2) zugestellt. .LP Beachten Sie, dass das killende Signal zuerst einen Signallieferstopp (auf nur einen verfolgten Prozess) verursachen wird und nur nachdem es durch den Verfolger eingespeist wurde (oder nachdem es an einen nicht verfolgten Thread versandt wurde), wird der Tod von dem Signal auf \fIalle\fP verfolgten Prozesse innerhalb eines Prozesses mit mehreren Threads ausgehen. (Der Begriff »Signallieferstopp« wird nachfolgend erklärt.) .LP \fBSIGKILL\fP erzeugt keinen »Signallieferstopp«. Daher kann der Verfolger es nicht unterdrücken. \fBSIGKILL\fP killt sogar innerhalb von Systemaufrufen (der Systemaufrufbeendigungsstopp wird nicht vorrangig vor dem Tod durch \fBSIGKILL\fP erzeugt). Der reine Effekt besteht darin, dass \fBSIGKILL\fP den Prozess (all seine Threads) immer killt, sogar dann, wenn einige Threads des Prozesses verfolgt werden. .LP Wenn der verfolgte Prozess \fB_exit\fP(2) aufruft, meldet er seinem Verfolger seinen Tod. Andere Threads werden nicht beeinflusst. .LP Wenn irgendein Thread \fBexit_group\fP(2) ausführt, meldet jeder verfolgte Prozess in dessen Gruppe seinen Tod an den Verfolger. .LP Falls die Option \fBPTRACE_O_TRACEEXIT\fP aktiv ist, wird \fBPTRACE_EVENT_EXIT\fP vor dem tatsächlichen Tod auftreten. Dies wird angewandt, um mittels \fBexit\fP(2), \fBexit_group\fP(2) und Todessignalen (ausgenommen \fBSIGKILL\fP) zu beenden und wenn Threads bei \fBexecve\fP(2) in einem Prozess mit mehreren Threads zerrissen werden. .LP Der Verfolger kann nicht abschätzen, ob der von Ptrace gestoppte Prozess existiert. Es gibt mehrere Szenarien, in denen der verfolgte Prozess sterben kann, während er gestoppt ist (wie \fBSIGKILL\fP). Daher muss der Verfolger vorbereitet werden, bei allen Ptrace\-Transaktionen einen \fBESRCH\fP\-Fehler zu handhaben. Leider wird der gleiche Fehler zurückgegeben, falls der verfolgte Prozess existiert, aber nicht von Ptrace gestoppt wurde (für Befehle, die einen gestoppten, verfolgten Prozess erfordern) oder falls er nicht durch den Prozess verfolgt wird, der den Ptrace\-Aufruf abschickte. Der Verfolger muss den Überblick über den »laufend«\-/»gestoppt«\-Status des verfolgten Prozesses behalten und \fBESRCH\fP nur dann als »verfolgter Prozess starb unerwartet« interpretieren, falls er weiß, dass der verfolgte Prozess beobachtet wurde, um in einen Ptrace\-stopp einzutreten. Beachten Sie, dass es keine Garantie gibt, dass \fIwaitpid(WNOHANG)\fP zuverlässig den Todesstatus des verfolgten Prozesses meldet, falls eine Ptrace\-Transaktion \fBESRCH\fP zurückgibt. \fIwaitpid(WNOHANG)\fP könnte stattdessen 0 zurückgeben. In anderen Worten kann es sein, dass der verfolgte Prozess »noch nicht vollständig tot« ist, aber bereits Ptrace\-Anfragen ablehnt. .LP Der Verfolger kann nicht abschätzen, ob der verfolgte Prozess \fIimmer\fP sein Leben durch melden von \fIWIFEXITED(status)\fP oder \fIWIFSIGNALED(status)\fP aushaucht. Es gibt Fälle, in denen dies nicht geschieht. Falls ein Thread, der nicht führender Thread der Thread\-Gruppe ist, zum Beispiel ein \fBexecve\fP(2) ausführt, verschwindet er; seine PID wird nie wieder gesehen und alle nachfolgenden Ptrace\-Stopps werden unter der PID des führenden Threads der Thread\-Gruppe gemeldet. .SS Gestoppt\-Status Ein verfolgter Prozess kann zwei Status haben: laufend oder gestoppt. Für die Zwecke von Ptrace wird ein durch einen Systemaufruf (wie \fBread\fP(2), \fBpause\fP(2), etc.) blockierter verfolgter Prozess dennoch als laufend betrachtet, sogar, wenn der verfolgte Prozess für lange Zeit blockiert ist. Der Status des verfolgten Prozesses nach \fBPTRACE_LISTEN\fP ist eine Grauzone: Er ist nicht in einem Ptrace\-Stopp (Ptrace\-Befehle funktionieren nicht bei ihm und er wird \fBwaitpid\fP(2)\-Benachrichtigungen übermitteln), aber er kann auch als »gestoppt« angesehen werden, da er keine Anweisungen ausführt (ist nicht eingeplant) und falls er vor \fBPTRACE_LISTEN\fP in einem Gruppenstopp war, wird er nicht auf Signale antworten, bis er \fBSIGCONT\fP empfängt. .LP Es gibt viele Arten von Status, wenn ein verfolgter Prozess gestoppt wurde und in Ptrace\-Diskussionen werden sie oft durcheinandergebracht. Daher ist es wichtig, präzise Begriffe zu verwenden. .LP In dieser Handbuchseite wird jeder Gestoppt\-Status, in dem der verfolgte Prozess bereit ist, Ptrace\-Befehle vom Verfolger zu akzeptieren, \fIPtrace\-Stopp\fP genannt. Ptrace\-Stopps können weiter in \fISignallieferstopp\fP, \fIGruppenstopp\fP und so fort unterteilt werden. Diese gestoppten Status werden nachfolgend im Detail beschrieben. .LP Wenn der laufende, verfolgte Prozess in Ptrace\-Stopp eintritt, benachrichtigt er seinen Verfolger mittels \fBwaitpid\fP(2) (oder einem anderen der »wait«\-Systemaufrufe). Meistens geht diese Handbuchseite davon aus, dass der Verfolger wartet mit: .LP PID = waitpid(pid_or_minus_1, &status, __WALL); .LP .\" Denys Vlasenko: .\" Do we require __WALL usage, or will just using 0 be ok? (With 0, .\" I am not 100% sure there aren't ugly corner cases.) Are the .\" rules different if user wants to use waitid? Will waitid require .\" WEXITED? .\" Mit Ptrace\-Stopp angehaltene, verfolgte Prozesse werden als Rückgaben mit \fIPID\fP größer als 0 und »\fIWIFSTOPPED(status)\fP true« gemeldet. .LP Der Schalter \fB__WALL\fP enthält nicht die Schalter \fBWSTOPPED\fP und \fBWEXITED\fP, impliziert aber ihre Funktionalität. .LP Es wird nicht empfohlen, den Schalter \fBWCONTINUED\fP zu setzen, wenn \fBwaitpid\fP(2) aufgerufen wird: Der Status »continued« gilt pro Prozess und ihn zu verbrauchen, kann den echten Elternprozess des verfolgten Prozesses verwirren. .LP Die Benutzung des Schalters \fBWNOHANG\fP könnte \fBwaitpid\fP(2) veranlassen, 0 zurückzugeben (»nocht keine Warteergebnisse verfügbar«), sogar dann, wenn der Verfolger weiß, dass dort eine Benachrichtigung sein soll. Beispiel: .nf errno = 0; ptrace(PTRACE_CONT, pid, 0L, 0L); if (errno == ESRCH) { /* verfolgter Prozess ist tot */ r = waitpid(tracee, &status, __WALL | WNOHANG); /* r kann hier immer noch 0 sein! */ } .fi .\" FIXME . .\" waitid usage? WNOWAIT? .\" describe how wait notifications queue (or not queue) .LP Die folgenden Arten von Ptrace\-Stopps existieren: Signallieferstopps, Gruppenstopps, \fBPTRACE_EVENT\fP\-Stopps und Systemaufrufstopps. Sie alle werden von \fBwaitpid\fP(2) mit »\fIWIFSTOPPED(status)\fP true« gemeldet. Sie könnten durch Untersuchen des Wertes \fIstatus>>8\fP unterschieden werden und, falls es eine Unklarheit im Wert gibt, durch Abfragen von \fBPTRACE_GETSIGINFO\fP. (Hinweis: Das Makro \fIWSTOPSIG(status)\fP kann nicht für diese Untersuchung verwandt werden, da es den Wert \fI(status>>8)\ &\ 0xff\fP zurückgibt.) .SS Signallieferstopp Wenn ein Prozess (möglicherweise mit mehreren Threads) ein Signal außer \fBSIGKILL\fP empfängt, wählt der Kernel einen beliebigen Thread aus, der das Signal handhabt. (Falls das Signal mit \fBtgkill\fP(2) erzeugt wurde, kann der Ziel\-Thread explizit durch den Aufrufenden ausgewählt werden.) Falls der ausgewählte Thread verfolgt wird, tritt er in einen Signallieferstopp ein. An diesem Punkt wird das Signal noch nicht an den Prozess zugestellt und kann durch den Verfolger unterdrückt werden. Falls der Verfolger das Signal nicht unterdrückt, übergibt er das Signal bei der nächsten Ptrace\-Neustartanfrage an den verfolgten Prozess. Dieser zweite Schritt der Signalzustellung wird in dieser Handbuchseite \fISignaleinspeisung\fP genannt. Beachten Sie, dass, falls das Signal blockiert ist, der Signallieferstopp nicht auftritt, bis die Blockade des Signals aufgehoben wurde, mit der üblichen Ausnahme, dass \fBSIGSTOP\fP nicht blockiert werden kann. .LP Der Signallieferstopp wird vom Verfolger als \fBwaitpid\fP(2) beobachtet und kehrt mit »\fIWIFSTOPPED(status)\fP true« mit dem Signal zurück, das von \fIWSTOPSIG(status)\fP zurückgegeben wurde. Falls das Signal \fBSIGTRAP\fP ist, könnte dies eine andere Art eines Ptrace\-Stopps sein; Einzelheiten finden Sie in den Abschnitten »Systemaufrufstopps« und »execve« unterhalb. Falls \fIWSTOPSIG(status)\fP ein stoppendes Signal zurückgibt, könnte dies ein Gruppenstopp sein; siehe unten. .SS "Signaleinspeisung und \-unterdrückung" Nachdem der Signallieferstopp durch den Verfolger beobachtet wurde, sollte der Verfolger den verfolgten Prozess mit dem Aufruf .LP ptrace(PTRACE_restart, PID, 0, Signal) .LP neu starten, wobei \fBPTRACE_restart\fP einer der neu startenden Ptrace\-Anfragen ist. Falls \fISignal\fP 0 ist, wird das Signal nicht zugestellt. Andernfalls wird das Signal \fISignal\fP zugestellt. Diese Transaktion wird in dieser Handbuchseite \fISignaleinspeisung\fP genannt, um sie vom Signallieferstopp zu unterscheiden. .LP Der \fISignal\fPwert kann sich vom Wert \fIWSTOPSIG(status)\fP unterschieden: Der Verfolger kann veranlassen, dass ein anderes Signal eingespeist wird. .LP Beachten Sie, dass ein unterdrücktes Signal immer noch Systemaufrufe verursacht, um vorzeitig zurückzukehren. In diesem Fall werden Systemaufrufe neu gestartet: Der Verfolger wird den verfolgten Prozess beobachten, um den unterbrochenen Systemaufruf neu auszuführen (oder den Systemaufruf \fBrestart_syscall\fP(2) für wenige Systemaufrufe, die unterschiedliche Mechanismen zum erneuten Starten verwenden), falls der Verfolger \fBPTRACE_SYSCALL\fP benutzt. Sogar Systemaufrufe (wie \fBpoll\fP(2)), die nach einem Signal nicht mehr neu startbar sind, werden nach dem Unterdrücken des Signals neu gestartet werden. Es existieren jedoch einige Kernelfehler, die zum Fehlschlagen einiger Systemaufrufe mit \fBEINTR\fP führen, sogar, wenn kein beobachtbares Signal in den verfolgten Prozess eingespeist wurde. .LP Es wird nicht garantiert, dass beim Neustarten von Ptrace\-Befehlen, die in anderen Ptrace\-Stopps als Signallieferstopps angestoßen wurden,ein Signal eingespeist wird, nicht einmal, wenn \fISignal\fP nicht Null ist. Es wird kein Fehler gemeldet; ein \fISignal\fP ungleich Null könnte einfach ignoriert werden. Ptrace\-Benutzer sollten nicht versuchen, auf diese Art »ein neues Signal zu erzeugen«: Benutzen Sie stattdessen \fBtgkill\fP(2). .LP Die Tatsache, dass Signaleinspeisungsanfragen beim erneuten Starten des verfolgten Prozesses nach Ptrace\-Stopps, die keine Signallieferstopps sind, ignoriert werden können, ist ein Grund für Verwirrung bei Ptrace\-Benutzern. Ein typisches Szenario ist, dass der Verfolger Gruppenstopps beobachtet, sie fälschlicherweise für Signallieferstopps hält und den verfolgen Prozess mit ptrace(PTRACE_restart, PID, 0, Stoppsignal) neu startet mit der Absicht \fIStoppsignal\fP einzuspeisen, \fIStoppsignal\fP aber ignoriert wird und der verfolgte Prozess weiter läuft. .LP Das Signal \fBSIGCONT\fP hat einen Seiteneffekt, dass es einen Prozess im Gruppenstopp (alle Threads davon) aufweckt. Dieser Seiteneffekt tritt vor dem Signallieferstopp auf. Der Verfolger kann diesen Seiteneffekt nicht unterdrücken (er kann nur Signaleinspeisung unterdrücken, was nur dazu führt, dass die \fBSIGCONT\fP\-Handhabung nicht im verfolgten Prozess ausgeführt wird, falls eine solche Handhabung installiert ist). Tatsächlich könnte dem Aufwecken aus den Gruppenstopp ein Signallieferstopp für \fIandere\fP Signale als \fBSIGCONT\fP folgen, falls sie ausstehen, wenn \fBSIGCONT\fP gesandt wurde. In anderen Worten könnte es sein, dass \fBSIGCONT\fP nicht das erste durch den Verfolger beobachtete Signal ist, nachdem es gesandt wurde. .LP Stoppen von Signalen führt dazu, das ein Prozess (alle Treads davon) in einen Gruppenstopp eintreten. Dieser Seiteneffekt tritt nach der Signaleinspeisung auf und kann daher durch den Verfolger unterdrückt werden. .LP .\" In the Linux 2.4 sources, in arch/i386/kernel/signal.c::do_signal(), .\" there is: .\" .\" /* The debugger continued. Ignore SIGSTOP. */ .\" if (signr == SIGSTOP) .\" continue; In Linux 2.4 und älter kann das Signal \fBSIGSTOP\fP nicht eingespeist werden. .LP \fBPTRACE_GETSIGINFO\fP kann benutzt werden, um eine \fIsiginfo_t\fP\-Struktur zu erhalten, die dem gesandten Signal entspricht. \fBPTRACE_SETSIGINFO\fP kann benutzt werden, um es zu verändern. Falls \fBPTRACE_SETSIGINFO\fP benutzt wurde, um \fIsiginfo_t\fP zu verändern, müssen das Feld \fIsi_signo\fP und der Parameter \fISignal\fP im Befehl zum Neustart übereinstimmen, andernfalls ist das Ergebnis undefiniert. .SS Gruppenstopp Wenn ein Prozess (der möglicherweise aus mehreren Threads besteht) ein Stoppsignal empfängt, werden alle Threads gestoppt. Falls einige Threads verfolgt werden, treten sie in eine Thread\-Gruppe ein. Beachten Sie, dass das Stoppsignal zuerst einen Signallieferstopp verursachen wird (nur auf den verfolgten Prozess) und nur, nachdem es durch den Verfolger eingespeist wurde (oder nachdem es an einen Thread geschickt wurde, der nicht verfolgt wird), wird der Gruppenstopp auf \fIalle\fP verfolgten Prozesse innerhalb eines Prozesses aus mehreren Threads eingeleitet. Wie üblich meldet jeder verfolgte Prozess seinen Gruppenstopp separat an den entsprechenden Verfolger. .LP Der Gruppenstopp wird vom Verfolger als \fBwaitpid\fP(2) beobachtet und kehrt mit »\fIWIFSTOPPED(status)\fP true« mit dem Stoppsignal zurück, das über \fIWSTOPSIG(status)\fP verfügbar ist. Dasselbe Ergebnis wird von einigen anderen Klassen von Ptrace\-Stopps zurückgegeben, daher ist die empfohlene Vorgehensweise, folgenden Aufruf zu tätigen: .LP ptrace(PTRACE_GETSIGINFO, PID, 0, &siginfo) .LP Der Aufruf kann vermieden werden, falls das Signal nicht \fBSIGSTOP\fP, \fBSIGTSTP\fP, \fBSIGTTIN\fP oder \fBSIGTTOU\fP ist. Nur diese vier Signale sind Stoppsignale. Falls der Verfolger etwas anderes sieht, kann es kein Gruppenstopp sein. Andernfalls benötigt der Verfolger den Aufruf \fBPTRACE_GETSIGINFO\fP. Falls \fBPTRACE_GETSIGINFO\fP mit \fBEINVAL\fP fehlschlägt, ist es definitiv ein Gruppenstopp. (Andere Fehlerkodes wie \fBESRCH\fP (»kein derartiger Prozess«) sind möglich, falls ein \fBSIGKILL\fP den verfolgten Prozess gekillt hat. .LP Falls ein verfolgter Prozess mittels \fBPTRACE_SEIZE\fP angehängt wurde, wird ein Gruppenstopp durch \fBPTRACE_EVENT_STOP\fP angezeigt: \fIStatus>>16 == PTRACE_EVENT_STOP\fP. Dies ermöglicht, einen Gruppenstopp festzustellen, ohne dass ein zusätzlicher \fBPTRACE_GETSIGINFO\fP\-Aufruf erforderlich ist. .LP Ab Linux 2.6.38 wird der verfolgte Prozess, nachdem der Verfolger den Ptrace\-Stopp des verfolgten Prozesses sieht und bis er neu startet oder ihn killt, nicht laufen und keine Benachrichtigungen an den Verfolger senden (außer dem Tod durch \fBSIGKILL\fP), nicht einmal, wenn der Verfolger in einen anderen \fBwaitpid\fP(2)\-Aufruf gelangt. .LP Das im vorhergehenden Absatz beschriebene Verhalten verursacht ein Problem bei transparenter Behandlung von Stoppsignalen. Falls der Verfolger den verfolgten Prozess nach einem Gruppenstopp neu startet, wird das Stoppsignal effektiv ignoriert \(emder verfolgte Prozess bleibt nicht gestoppt, er läuft. Falls der Verfolger den verfolgten Prozess neu startet, bevor er in das nächste \fBwaitpid\fP(2) eintritt, werden zukünftige \fBSIGCONT\fP\-Signale nicht an den Verfolger gemeldet. Dies würde dazu führen, dass die \fBSIGCONT\fP\-Signale keine Auswirkungen auf den verfolgten Prozess haben. .LP Seit Linux 3.4 gibt es eine Methode, die dieses Problem bewältigt: Statt \fBPTRACE_CONT\fP kann ein \fBPTRACE_LISTEN\fP\-Befehl zum Neustart eines verfolgten Prozesses auf eine Weise benutzt werden, die ihn nicht ausführt, aber auf ein neues Ereignis wartet, das er über \fBwaitpid\fP(2) melden kann, wenn er zum Beispiel mit \fBSIGCONT\fP neu gestartet wird. .SS PTRACE_EVENT\-Stopps Falls der Verfolger \fBPTRACE_O_TRACE_*\fP\-Optionen setzt, wird der verfolgte Prozess in \fBPTRACE_EVENT\fP\-Stopps genannte Stopps gelangen. .LP \fBPTRACE_EVENT\fP\-Stopps werden durch den Verfolger als als \fBwaitpid\fP(2) beobachtet, kehren mit »\fIWIFSTOPPED(status)\fP true« zurück und \fIWSTOPSIG(status)\fP gibt \fBSIGTRAP\fP zurück. Es wird ein zusätzliches Bit in das höhere Bit des Status (Datentyp Word) gesetzt: Der Wert \fIstatus>>8\fP wird wie folgt sein: (SIGTRAP | PTRACE_EVENT_foo << 8). Es gibt die folgenden Ereignisse: .TP \fBPTRACE_EVENT_VFORK\fP stoppt vor dem Zurückkehren von \fBvfork\fP(2) oder \fBclone\fP(2) mit dem Schalter \fBCLONE_VFORK\fP. Wenn der verfolgte Prozess nach diesem Stopp fortgeführt wird, wird er auf das Beenden/Ausführen des Kindprozesses warten, bevor er mit seiner Ausführung fortfährt (in anderen Worten, das übliche Verhalten auf \fBvfork\fP(2)). .TP \fBPTRACE_EVENT_FORK\fP stoppt vor dem Zurückkehren von \fBfork\fP(2) oder \fBclone\fP(2) mit dem auf \fBSIGCHLD\fP gesetzten Beendigungssignal. .TP \fBPTRACE_EVENT_CLONE\fP stoppt vor dem Zurückkehren von \fBclone\fP(2). .TP \fBPTRACE_EVENT_VFORK_DONE\fP stoppt vor dem Zurückkehren von \fBvfork\fP(2) oder \fBclone\fP(2) mit dem Schalter \fBCLONE_VFORK\fP, aber nachdem die Blockade dieses verfolgten Prozesses durch Beenden oder Ausführung aufgehoben wurde. .LP Für alle vier oben beschriebenen Stopps tritt der Stopp im Elternprozess auf (d.h. im verfolgenden Prozess), nicht im neu erstellten Thread. \fBPTRACE_GETEVENTMSG\fP kann benutzt werden, um die Kennung des neuen Threads zu erhalten. .TP \fBPTRACE_EVENT_EXEC\fP stoppt vor dem Zurückkehren von \fBexecve\fP(2). Ab Linux 3.0, gibt \fBPTRACE_GETEVENTMSG\fP die vorherige Thread\-Kennung zurück. .TP \fBPTRACE_EVENT_EXIT\fP stoppt vor dem Beenden (einschließlich des Todes aus \fBexit_group\fP(2)), dem Signaltod oder endet, verursacht durch \fBexecve\fP(2), in einem Prozess aus mehreren Threads. \fBPTRACE_GETEVENTMSG\fP gibt den Exit\-Status zurück. Register können untersucht werden (solange nicht »wirklich« beendet wird). Der verfolgte Prozess ist immer noch lebendig; er benötigt zum Fertigstellen des Beendens \fBPTRACE_CONT\fP oder \fBPTRACE_DETACH\fP. .TP \fBPTRACE_EVENT_STOP\fP Stopp, der durch einen \fBPTRACE_INTERRUPT\fP\-Befehl, einen Gruppenstopp oder ein »ptrace\-stop« zu Beginn veranlasst wurde, wenn ein neuer Kindprozess angehängt wird (nur beim Anhängen mittels \fBPTRACE_SEIZE\fP) oder \fBPTRACE_EVENT_STOP\fP, falls \fBPTRACE_SEIZE\fP benutzt wurde .LP \fBPTRACE_GETSIGINFO\fP auf \fBPTRACE_EVENT\fP\-Stopps gibt \fBSIGTRAP\fP in \fIsi_signo\fP zurück, wobei \fIsi_code\fP auf \fI(event<<8)\ |\ SIGTRAP\fP gesetzt ist. .SS Systemaufrufstopps Falls der verfolgte Prozess durch \fBPTRACE_SYSCALL\fP neu gestartet wurde, gerät der verfolgte Prozess in einen Systemaufrufeintrittsstopp kurz vor dem Eintritt in irgendeinen Systemaufruf. Falls der Verfolger den verfolgten Prozess mit \fBPTRACE_SYSCALL\fP neu startet, gerät der verfolgte Prozess in einen Systemaufrufbeendigungsstopp, wenn der Systemaufruf beendet ist oder falls er durch ein Signal unterbrochen wurde. (Sprich, der Signallieferstopp tritt nie zwischen Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp auf; er findet \fInach\fP dem Systemaufrufbeendigungsstopp statt.) .LP Andere Möglichkeiten sind, dass der verfolgte Prozess in einem \fBPTRACE_EVENT\fP\-Stopp stoppen könnte, endet (falls er in \fB_exit\fP(2) oder \fBexit_group\fP(2) eintritt), durch \fBSIGKILL\fP gekillt wird oder leise stirbt (falls er die Thread\-Gruppe anführt, kommt das \fBexecve\fP(2) in einem anderen Thread vor und der Thread wird nicht vom selben Verfolger verfolgt; diese Situation wird später besprochen). .LP Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp werden vom Verfolger als als \fBwaitpid\fP(2) beobachtet, kehren mit »\fIWIFSTOPPED(status)\fP true« zurück und \fIWSTOPSIG(status)\fP gibt \fBSIGTRAP\fP zurück. Falls die Option \fBPTRACE_O_TRACESYSGOOD\fP durch den Verfolger gesetzt wurde, wird \fIWSTOPSIG(status)\fP den Wert \fI(SIGTRAP\ |\ 0x80)\fP zurückgeben. .LP Systemaufrufstopps können von Signallieferstopps mit \fBSIGTRAP\fP durch Abfrage von \fBPTRACE_GETSIGINFO\fP für die folgenden Fälle unterschieden werden: .TP \fIsi_code\fP <= 0 \fBSIGTRAP\fP wurde mit einem Ergebnis einer Userspace\-Aktion, zum Beispiel einem Systemaufruf ((\fBtgkill\fP(2), \fBkill\fP(2), \fBsigqueue\fP(3), etc.), Ablauf eines POSIX\-Zeitnehmers, Statusänderung einer POSIX\-Nachrichtenwarteschlange oder Vervollständigung einer asynchronen E/A\-Anfrage geliefert. .TP \fIsi_code\fP == SI_KERNEL (0x80) \fBSIGTRAP\fP wurde vom Kernel gesandt. .TP \fIsi_code\fP == SIGTRAP or \fIsi_code\fP == (SIGTRAP|0x80) Dies ist ein Systemaufrufstopp. .LP Systemaufrufstopps kommen jedoch sehr oft vor (zweimal pro Systemaufruf) und das Ausführen von \fBPTRACE_GETSIGINFO\fP für jeden Systemaufrufstopp könnte etwas aufwendig sein. .LP Einige Architekturen erlauben, die Fälle durch Untersuchen der Register zu unterscheiden. Zum Beispiel auf x86, \fIrax\fP == \-\fBENOSYS\fP im Systemaufrufeintrittsstopp. Da \fBSIGTRAP\fP (wie jedes andere Signal) immer \fInach\fP dem Systemaufrufbeendigungsstopp auftritt und \fIrax\fP an diesem Punkt fast nie \fBENOSYS\fP enthält, sieht das \fBSIGTRAP\fP aus wie ein »Systemaufrufstopp, der kein Systemaufrufeintrittsstopp« ist; in anderen Worten, er sieht aus wie ein »herrenloser Systemaufrufbeendigungsstopp« und kann auf diese Art entdeckt werden. Aber eine solche Entdeckung ist fragil und wird am besten vermieden. .LP Die Benutzung der Option \fBPTRACE_O_TRACESYSGOOD\fP ist die empfohlene Methode, um Systemaufrufstopps von anderen Arten der Ptrace\-Stopps zu unterscheiden, da sie zuverlässig ist und sich keine Leistungseinbuße zuzieht. .LP Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp sind für den Verfolger nicht voneinander zu unterscheiden. Der Verfolger muss den Überblick über die Abfolge der Ptrace\-Stopps behalten, um nicht den Systemaufrufeintrittsstopp fälschlicherweise als Systemaufrufbeendigungsstopp oder umgekehrt zu interpretieren. Die Regel besagt, dass diesem Systemaufrufeintrittsstopp immer ein Systemaufrufbeendigungsstopp, \fBPTRACE_EVENT\fP\-Stopp oder der Tod des verfolgten Prozesses folgt; dazwischen können keine anderen Arten von Ptrace\-Stopps auftreten. .LP Falls der Verfolger nach dem Systemaufrufeintrittsstopp einen anderen Befehl zum Neustarten als \fBPTRACE_SYSCALL\fP verwendet, wird der Systemaufrufbeendigungsstopp nicht erzeugt. .LP \fBPTRACE_GETSIGINFO\fP auf Systemaufrufstopps gibt \fBSIGTRAP\fP in \fIsi_signo\fP zurück, wobei \fIsi_code\fP auf \fBSIGTRAP\fP oder \fI(SIGTRAP|0x80)\fP gesetzt ist. .SS "PTRACE_SINGLESTEP\-, PTRACE_SYSEMU\-, PTRACE_SYSEMU_SINGLESTEP\-Stopps" .\" .\" FIXME . .\" document stops occurring with PTRACE_SINGLESTEP, PTRACE_SYSEMU, .\" PTRACE_SYSEMU_SINGLESTEP [Einzelheiten dieser Arten von Stopps sind noch nicht dokumentiert.] .SS "Benachrichtigende und neustartende Ptrace\-Befehle" Die meisten Ptrace\-Befehle (alle außer \fBPTRACE_ATTACH\fP, \fBPTRACE_SEIZE\fP, \fBPTRACE_TRACEME\fP, \fBPTRACE_INTERRUPT\fP und \fBPTRACE_KILL\fP) erfordern, dass der verfolgte Prozess in einem Ptrace\-Stopp ist, andernfalls scheitern sie mit \fBESRCH\fP. .LP Wenn der verfolgte Prozess im Ptrace\-Stopp ist, kann der Verfolger Daten des verfolgten Prozesses mittels benachrichtigenden Befehlen lesen und schreiben. Diese Befehle belassen den verfolgten Prozess im Status Ptrace\-gestoppt: .LP .nf ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, PID, Adresse, 0); ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, PID, Adresse, 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); .fi .LP Beachten Sie, dass einige Fehler nicht gemeldet wurden. Das Setzen des Informationssignals (\fIsiginfo\fP) hat zum Beispiel in einigen Ptrace\-Stopps möglicherweise keine Auswirkungen, der Aufruf kann jedoch erfolgreich sein (0 zurückgeben und \fIerrno\fP nicht setzen); Abfragen von \fBPTRACE_GETEVENTMSG\fP könnte erfolgreich sein und einen zufälligen Wert zurückgeben, falls der aktuelle Ptrace\-Stopp nicht dokumentiert ist, um eine aussagekräftige Ereignisnachricht zuückzugeben. .LP Der Aufruf ptrace(PTRACE_SETOPTIONS, PID, 0, PTRACE_O_flags); beeinflusst einen verfolgten Prozess. Die aktuellen Schalter des verfolgten Prozesses werden ersetzt. Schalter werden geerbt durch neu erzeugte Prozesse und »automatisch angehängt« über aktive \fBPTRACE_O_TRACEFORK\fP\-, \fBPTRACE_O_TRACEVFORK\fP\- oder \fBPTRACE_O_TRACECLONE\fP\-Optionen. .LP Eine weitere Gruppe von Befehlen lässt die per Ptrace gestoppten, verfolgten Prozesse laufen. Sie haben die Form: .LP ptrace(Befehl, PID, 0, Signal); .LP wobei \fIBefehl\fP \fBPTRACE_CONT\fP, \fBPTRACE_LISTEN\fP, \fBPTRACE_DETACH\fP, \fBPTRACE_SYSCALL\fP, \fBPTRACE_SINGLESTEP\fP, \fBPTRACE_SYSEMU\fP oder \fBPTRACE_SYSEMU_SINGLESTEP\fP ist. Falls der verfolgte Prozess sich im Signallieferstopp befindet, ist \fISignal\fP das Signal, das eingespeist wird (falls es ungleich Null ist). Andernfalls kann \fISignal\fP ignoriert werden. (Wenn ein verfolgter Prozess von einem anderen Ptrace\-Stopp als dem Signallieferstopp neu gestartet wird, ist die empfohlene Vorgehensweise, 0 in \fISignal\fP zu übergeben.) .SS "Anhängen und Loslösen" Ein Thread kann an den Verfolger angehängt werden mit dem Aufruf ptrace(PTRACE_ATTACH, PID, 0, 0); oder ptrace(PTRACE_SEIZE, PID, 0, PTRACE_O_flags); .\" .\" FIXME . Describe how to attach to a thread which is already group-stopped. \fBPTRACE_ATTACH\fP sendet außerdem \fBSIGSTOP\fP an diesen Thread. Falls der Verfolger möchte, dass dieser \fBSIGSTOP\fP keine Auswirkungen hat, muss er ihn unterdrücken. Beachten Sie, dass der Verfolger, falls während des Anhängens gleichzeitig weitere Signale an diesen Thread gesandt werden, den Eintritt in den Signallieferstopp mit anderen Signalen zuerst sieht! Die übliche Vorgehensweise ist, diese Signale neu einzuspeisen, bis \fBSIGSTOP\fP gesehen wird und dann die Einspeisung von \fBSIGSTOP\fP zu unterdrücken. Der Entwurfsfehler ist hierbei, dass sich ein Ptrace\-Anhängen und ein gleichzeitig gesandtes \fBSIGSTOP\fP einen Wettlauf liefern und das gleichzeitige \fBSIGSTOP\fP verloren gegangen sein kann. .LP Da Anhängen \fBSIGSTOP\fP sendet und der Verfolger es üblicherweise unterdrückt, könnte dies zu einer herrenlosen \fBEINTR\fP\-Rückgabe vom aktuell ausgeführten Systemaufruf in diesem verfolgten Prozess führen, wie er im Abschnitt »Signaleinspeisung und \-unterdrückung« beschrieben wird. .LP Seit Linux 3.4 kann \fBPTRACE_SEIZE\fP anstelle von \fBPTRACE_ATTACH\fP benutzt werden. \fBPTRACE_SEIZE\fP stoppt nicht den angehängten Prozess. Falls Sie ihn nach dem Anhängen (oder zu einem anderen Zeitpunkt) stoppen wollen ohne irgendwelche Signale zu senden, verwenden Sie den Befehl \fBPTRACE_INTERRUPT\fP. .LP Die Anfrage ptrace(PTRACE_TRACEME, 0, 0, 0); verwandelt den aufrufenden Thread in einen verfolgten Prozess. Der Thread fährt mit der Ausführung fort (gerät nicht in den Ptrace\-Stopp). Eine übliche Vorgehensweise besteht darin, \fBPTRACE_TRACEME\fP mit raise(SIGSTOP); zu folgen und dem Elternprozess (der nun der Verfolger ist) zu ermöglichen, den Signallieferstopp zu beobachten. .LP Falls die Optionen \fBPTRACE_O_TRACEFORK\fP, \fBPTRACE_O_TRACEVFORK\fP oder \fBPTRACE_O_TRACECLONE\fP in Kraft sind, werden Kindprozesse mit \fBvfork\fP(2), beziehungsweise \fBclone\fP(2) mit dem Schalter \fBCLONE_VFORK\fP, \fBfork\fP(2) oder \fBclone\fP(2) mit auf \fBSIGCHLD\fP gesetztem Beendigungssignal und anderen Arten von \fBclone\fP(2) automatisch an den gleichen Verfolger angehängt, der ihren Elternprozess verfolgte. \fBSIGSTOP\fP wird an die Kindprozesse gesandt, was sie veranlasst, in einen Signallieferstopp zu gelangen, nachdem sie den Systemaufruf beenden, der sie erzeugt hat. .LP Loslösen des verfolgten Prozesses wird erreicht durch: ptrace(PTRACE_DETACH, PID, 0, Signal); \fBPTRACE_DETACH\fP ist eine Neustartoperation; daher erfordert sie, dass der verfolgte Prozess in einem Ptrace\-Stopp ist. Falls der verfolgte Prozess in einem Signallieferstopp ist, kann ein Signal eingespeist werden. Andernfalls wird der Parameter \fISignal\fP stillschweigend ignoriert. .LP .\" FIXME . Describe how to detach from a group-stopped tracee so that it .\" doesn't run, but continues to wait for SIGCONT. Falls der verfolgte Prozess läuft, wenn der Verfolger ihn loslösen möchte, besteht die übliche Lösung darin, \fBSIGSTOP\fP zu senden (mittels \fBtgkill\fP(2), um sicherzustellen, dass es an den korrekten Thread geht), darauf zu warten, dass der verfolgte Prozess in einen Signallieferstopp für \fBSIGSTOP\fP stoppt und ihn dann loszulösen (\fBSIGSTOP\fP\-Einspeisung wird unterdrückt). Ein Entwurfsfehler ist, dass sich dies mit gleichzeitigen \fBSIGSTOP\fPs Rennen liefern kann. Eine weitere Komplikation besteht darin, dass der verfolgte Prozess in andere Ptrace\-Stopps geraten kann und neu gestartet werden muss und nochmals wartet, bis \fBSIGSTOP\fP gesehen wird. Noch eine weitere Komplikation ist, dass nicht sicher ist, ob der verfolgte Prozess nicht bereits mit Ptrace gestoppt wurde, da keine Signallieferung stattfindet, obwohl es \(emnicht gerade \fBSIGSTOP\fP ist. .LP Falls der Verfolger stirbt, werden alle verfolgten Prozesse automatisch losgelöst und neu gestartet, es sei denn, sie sind im Gruppenstopp. Die Handhabung des Neustarts aus dem Gruppenstopp ist derzeit fehlerhaft, aber das »wie\-geplant«\-Verhalten ist, den verfolgten Prozess gestoppt zu lassen und auf \fBSIGCONT\fP zu warten. Falls der verfolgte Prozess neu vom Signallieferstopp gestartet wurde, wird das ausstehende Signal einspeist. .SS "execve(2) unter Ptrace" .\" clone(2) CLONE_THREAD says: .\" If any of the threads in a thread group performs an execve(2), .\" then all threads other than the thread group leader are terminated, .\" and the new program is executed in the thread group leader. .\" .\" In kernel 3.1 sources, see fs/exec.c::de_thread() Wenn ein Thread in einem Prozess mit mehreren Threads \fBexecve\fP(2) aufruft, zerstört der Kernel alle anderen Threads im Prozess und setzt die Thread\-Kennung des ausführenden Threads auf die Gruppenkennung (Prozesskennung) zurück. (Oder anders ausgedrückt, wenn ein Prozess mit mehreren Threads ein \fBexecve\fP(2) bei Vervollständigung des Aufrufs ausführt, scheint es durch das \fBexecve\fP(2) im führenden Thread der Prozessgruppe aufzutreten, unabhängig davon, welcher Thread das \fBexecve\fP(2) aufrief.) Dieses Zurücksetzen der Thread\-Kennung sieht für Verfolger sehr verwirrend aus: .IP * 3 Alle anderen Threads stoppen im \fBPTRACE_EVENT_EXIT\fP\-Stopp, falls die Option \fBPTRACE_O_TRACEEXIT\fP eingeschaltet wurde. Dann melden alle anderen Threads außer dem führenden Thread der Gruppe den Tod, als ob sie über \fB_exit\fP(2) mit dem Exit\-Kode 0 beendet worden wären. .IP * Der ausführende, verfolgte Prozess ändert seine Thread\-Kennung, während er in dem \fBexecve\fP(2) ist. (Denken Sie daran, unter Ptrace ist die von \fBwaitpid\fP(2) zurückgegebene oder in Ptrace\-Aufrufe gespeiste »PID«, die Thread\-Kennung des verfolgten Prozesses.) Sprich, die Thread\-Kennung des verfolgten Prozesses wird zurückgesetzt, so dass sie ihrer Prozesskennung entspricht, die dieselbe ist, wie die Thread\-Kennung des führenden Threads der Thread\-Gruppe. .IP * Dann kommt es zu einem \fBPTRACE_EVENT_EXEC\fP\-Stopp, falls die Option \fBPTRACE_O_TRACEEXEC\fP eingeschaltet wurde. .IP * Falls der führende Thread der Gruppe seinen \fBPTRACE_EVENT_EXEC\fP\-Stopp mittlerweile gemeldet hat, scheint es für den Verfolger, als ob der tote führende Thread »aus dem Nichts wieder auftaucht«. (Hinweis: Der führende Thread der Gruppe meldet den Tod nicht über \fIWIFEXITED(status)\fP bis es mindestens einen lebenden anderen Thread gibt. Dies eliminiert die Möglichkeit, dass der Verfolger ihn sterben und dann erneut erscheinen sieht.) Falls der führende Thread der Gruppe immer noch lebt, könnte dies für den Verfolger so aussehen, als ob der führende Thread der Gruppe von einem anderen Systemaufruf als dem beigetretenen zurückkehrt oder sogar »von einem Systemaufruf zurückkehrt, obwohl er in keinem Systemaufruf war«. Falls der führende Thread der Gruppe nicht verfolgt wurde (oder von einem anderen Verfolger verfolgt wurde), dann wird es während \fBexecve\fP(2) so aussehen, als ob er ein verfolgter Prozess des Verfolgers des ausführenden verfolgten Prozesses geworden wäre. .LP All die Auswirkungen oberhalb sind Artefakte des Thread\-Kennungswechsels im verfolgten Prozess. .LP Die Option \fBPTRACE_O_TRACEEXEC\fP ist das emfpohlene Werkzeug für den Umgang mit dieser Situation. Zuerst aktiviert es \fBPTRACE_EVENT_EXEC\fP\-Stopp, der vor der Rückkehr von \fBexecve\fP(2) auftritt. In diesem Stopp kann der Verfolger \fBPTRACE_GETEVENTMSG\fP verwenden, um die vorherige Thread\-Kennung des verfolgten Prozesses zu erhalten. (Diese Funktion wurde in Lunux 3.0 eingeführt.) Als zweites deaktiviert die Option \fBPTRACE_O_TRACEEXEC\fP die alte \fBSIGTRAP\fP\-Erzeugung auf \fBexecve\fP(2). .LP Wenn der Verfolger die \fBPTRACE_EVENT_EXEC\fP\-Stoppbenachrichtigung empfängt, ist garantiert, dass außer diesem verfolgten Prozess und dem führenden Thread der Gruppe keine anderen Threads des Prozesses lebendig sind. .LP Beim Empfang der \fBPTRACE_EVENT_EXEC\fP\-Stoppbenachrichtigung sollte der Verfolger all seine internen Datenstrukturen aufräumen, die Threads dieses Prozesses beschreiben und nur eine Datenstruktur behalten, \(emeine, die den einzelnen, laufenden, verfolgten Prozess beschreibt mit Thread\-Kennung == Thread\-Gruppenkennung == Prozesskennung. .LP Beispiel: Zwei Thread rufen zur gleichen Zeit \fBexecve\fP(2) auf: .LP .nf *** wir bekommen einen Systemaufrufeintrittsstopp in Thread 1: ** PID1 execve("/bin/foo", "foo" *** wir liefern PTRACE_SYSCALL für Thread 1 ** *** wir bekommen einen Systemaufrufeintrittsstopp in Thread 2: ** PID2 execve("/bin/bar", "bar" *** wir liefern PTRACE_SYSCALL für Thread 2 ** *** wir bekommen PTRACE_EVENT_EXEC für PID0, wir liefern PTRACE_SYSCALL ** *** wir bekommen Systemaufrufbeendigungsstopp für PID0: ** PID0 <… execve wieder aufgenommen> ) = 0 .fi .LP Falls die Option \fBPTRACE_O_TRACEEXEC\fP für den ausführenden, verfolgten Prozess \fInicht\fP in Kraft ist, sendet der Kernel ein zusätzliches \fBSIGTRAP\fP an den verfolgten Prozess, nachdem \fBexecve\fP(2) zurückgekehrt ist. Dies ist ein gewöhnliches Signal (ähnlich einem, das durch \fIkill \-TRAP\fP erzeugt werden kann), keine Spezialart eines Ptrace\-Stopps. Unter Einsatz von \fBPTRACE_GETSIGINFO\fP für dieses Signal gibt \fIsi_code\fP auf 0 gesetzt (\fISI_USER\fP) zurück. Dieses Signal kann durch die Signalmaske blockiert sein und könnte daher (viel) später gesandt werden. .LP Üblicherweise würde der Verfolger dem Anwender dieses zusätzliche \fBSIGTRAP\fP\-Signal nach Execve nicht zeigen wollen und seinen Versand an den verfolgten Prozess unterdrücken (falls \fBSIGTRAP\fP auf \fBSIGTRAP\fP gesetzt ist, killt es das Signal). Es ist jedoch nicht einfach zu bestimmen, \fIwelches\fP \fBSIGTRAP\fP zu unterdrücken ist. Die empfohlene Herangehensweise ist, die Option \fBPTRACE_O_TRACEEXEC\fP zu setzen und daher dieses zusätzliche \fBSIGTRAP\fP zu unterdrücken. .SS "Echter Elternprozess" Die Ptrace\-Programmierschnittstelle (miss)braucht die Standard\-UNIX\-Eltern\-/Kindprozess\-Signalgebung über \fBwaitpid\fP(2). Diese wird benutzt, um den echten Elternprozess zum Stopp des Empfangs mehrerer Arten von \fBwaitpid\fP(2)\-Benachrichtigungen zu veranlassen, wenn der Kindprozess durch einen anderen Prozess verfolgt wird. .LP Viele dieser Fehler wurden behoben, aber ab Linux 2.6.38 existieren etliche immer noch; siehe FEHLER oberhalb. .LP Ab Linux 2.6.38 wird davon ausgegangen, dass das folgende korrekt funktioniert: .IP * 3 Beenden/Sterben durch Signal wird zuerst an den Verfolger gemeldet, dann, wenn der Verfolger das \fBwaitpid\fP(2)\-Ergebnis verbraucht, an den echten Elternprozess (an den echten Elternprozess nur, wenn der ganze Prozess aus mehreren Threads existiert). Falls der Verfolger und der echte Elternprozess derselbe Prozess sind, wird der Bericht nur einmal gesandt. .SH RÜCKGABEWERT Bei Erfolg geben die \fBPTRACE_PEEK*\fP\-Anfragen die angeforderten Daten zurück (aber siehe die ANMERKUNGEN), während andere Anfragen null zurückgeben. .LP Bei einem Fehler geben alle Anfragen \-1 zurück und \fIerrno\fP wird entsprechend gesetzt. Da der Wert, der von einer erfolgreichen \fBPTRACE_PEEK*\fP\-Anfrage zurückgegeben wurde, \-1 sein könnte, muss der Aufrufende vor dem Aufruf \fIerrno\fP leeren und es dann hinterher untersuchen, um festzustellen, ob ein Fehler aufgetreten ist oder nicht. .SH FEHLER .TP \fBEBUSY\fP (nur i386) Es ist beim Reservieren oder der Freigabe eines Debug\-Registers ein Fehler aufgetreten. .TP \fBEFAULT\fP Es gab einen Versuch in einem ungültigen Bereich im Speicher des Verfolgers oder des verfolgten Prozesses zu lesen oder zu schreiben, wahrscheinlich, weil der Bereich nicht abgebildet war oder kein Zugriff möglich war. Unglücklicherweise geben unter Linux mehrere Variationen dieser Störung mehr oder weniger willkürlich \fBEIO\fP oder \fBEFAULT\fP zurück. .TP \fBEINVAL\fP Es wurde versucht, eine ungültige Option zu setzen. .TP \fBEIO\fP \fIAnfrage\fP ist ungültig, es wurde versucht, in einem ungültigen Bereich im Speicher des Verfolgers oder des verfolgten Prozesses zu lesen oder zu schreiben, es gab eine Verletzung der Ausrichtung an der »word«\-Größe oder es wurde während des Neustarts der Abfrage ein ungültiges Signal angegeben. .TP \fBEPERM\fP Der angegebene Prozess kann nicht verfolgt werden. Dies könnte daher rühren, dass der Verfolger über unzureichende Privilegien verfügt (die Fähigkeit \fBCAP_SYS_PTRACE\fP wird benötigt); unprivilegierte Prozesse können keine Prozesse verfolgen, denen sie keine Signale senden können oder die SUID\-/SGID\-Programme ausführen, was naheliegend ist. Alternativ könnte der Prozess bereits verfolgt werden oder (auf Kerneln vor 2.6.26) \fBinit\fP(8) (PID 1) sein. .TP \fBESRCH\fP Der angegebene Prozess existiert nicht, wird derzeit nicht vom Aufrufenden verfolgt oder ist nicht gestoppt (bei Anfragen, die einen gestoppten verfolgten Prozess erfordern). .SH "KONFORM ZU" SVr4, 4.3BSD. .SH ANMERKUNGEN Obwohl Argumente für \fBptrace\fP() gemäß dem angegebenen Prototypen interpretiert werden, deklariert Glibc derzeit \fBptrace\fP() als eine variable Funktion mit nur dem festen \fIAnfrage\fP\-Argument. Es wird empfohlen, immer vier Argumente anzugeben, sogar dann, wenn die angeforderte Transaktion sie nicht verwendet. Setzen Sie unbenutzte/ignorierte Argumente auf \fI0L\fP oder \fI(void\ *)\ 0\fP. .LP .\" See commit 00cd5c37afd5f431ac186dd131705048c0a11fdb In Linux\-Kerneln vor 2.6.26 kann \fBinit\fP(8) den Prozess mit der Prozessnummer 1 nicht verfolgen. .LP .\" See http://lkml.org/lkml/2008/5/8/375 Das Layout des Speicherinhalts und des BENUTZERbereichs sind ziemlich Betriebsystem\- und Architekturspezifisch. Der mitgelieferte Versatz und die zurückgegebenen Daten passen möglicherweise nicht ganz zu der Definition von \fIstruct user\fP. .LP Die Größe eines »word« wird durch die Betriebsystemvariante festgelegt (z.B. ist es für ein 32\-Bit\-Linux 32 Bit). .LP Diese Seite dokumentiert die Möglichkeit, wie der \fBptrace\fP()\-Aufruf derzeit in Linux arbeitet. Sein Verhalten unterscheidet sich auf anderen unixoiden Betriebssystemen deutlich. Auf jeden Fall ist die Benutzung von \fBptrace\fP() in hohem Grad abhängig vom Betriebssystem und der Architektur. .SS "ABI\-Unterschiede in C\-Bibliothek/Kernel" Auf der Systemaufrufebene haben die Anfragen \fBPTRACE_PEEKTEXT\fP, \fBPTRACE_PEEKDATA\fP und \fBPTRACE_PEEKUSER\fP eine unterschiedliche Programmierschnittstelle: Sie speichern das Ergebnis an der durch den Parameter \fIDaten\fP angegebenen Adresse und der Rückgabewert ist ein Fehlercode. Die Glibc\-Wrapper\-Funktion stellt die oben in BESCHREIBUNG angegebene Programmierschnittstelle bereit. Ihr Ergebnis wird über den Rückgabewert der Funktion zurückgegeben. .SH FEHLER Auf Rechnern mit 2.6 Kernel\-Headern ist \fBPTRACE_SETOPTIONS\fP mit einem anderen Wert deklariert, als auf einem für 2.4. Dies führt dazu, dass Anwendungen, die mit 2.6\-Kernel\-Headern kompiliert wurden, bei der Ausführung auf 2.4er Kerneln scheitern. Dies kann durch Neudefinieren von \fBPTRACE_SETOPTIONS\fP zu \fBPTRACE_OLDSETOPTIONS\fP umgangen werden, wenn dies definiert ist. .LP Gruppenstoppbenachrichtigungen werden an der Verfolger gesandt, aber nicht an den echten Elternprozess. Zuletzt auf 2.6.38.6 bestätigt. .LP .\" Note from Denys Vlasenko: .\" Here "exits" means any kind of death - _exit, exit_group, .\" signal death. Signal death and exit_group cases are trivial, .\" though: since signal death and exit_group kill all other threads .\" too, "until all other threads exit" thing happens rather soon .\" in these cases. Therefore, only _exit presents observably .\" puzzling behavior to ptrace users: thread leader _exit's, .\" but WIFEXITED isn't reported! We are trying to explain here .\" why it is so. .\" FIXME . need to test/verify this scenario Falls ein führender Thread einer Gruppe verfolgt und durch den Aufruf von \fB_exit\fP(2) beendet wird, wird es für ihn zu einem \fBPTRACE_EVENT_EXIT\fP\-Stopp kommen (falls angefordert), aber die nachfolgende \fBWIFEXITED\fP\-Benachrichtigung wird nicht gesandt, bis alle anderen Threads beendet sind. Wie oben erklärt, wird der Tod des führenden Prozesses der Gruppe gemeldet, falls einer der anderen Threads \fBexecve\fP(2) aufruft. Falls der ausgeführte Thread nicht durch den Verfolger verfolgt wird, wird der Verfolger niemals erfahren, dass \fBexecve\fP(2) auftrat. Eine mögliche Notlösung ist ein \fBPTRACE_DETACH\fP für den führenden Thread der Gruppe, anstatt ihn in diesem Fall neu zu starten. Zuletzt auf 2.6.38.6 bestätigt. .LP Ein \fBSIGKILL\fP\-Signal kann immer noch einen \fBPTRACE_EVENT_EXIT\fP\-Stopp vor dem tatsächlichen Signaltod verursachen. Dies könnte in Zukunft geändert werden; \fBSIGKILL\fP ist dazu gedacht, Aufgaben immer sofort zu killen, sogar unter Ptrace. Zuletzt auf 2.6.38.6 bestätigt. .LP Einige Systemaufrufe kehren mit \fBEINTR\fP zurück, falls ein Signal an den verfolgten Prozess gesandt, die Auslieferung aber durch den Verfolger unterdrückt wurde. (Dies ist eine ganz typische Transaktion: Sie wird normalerweise von Fehlersuchprogrammen bei jedem Anhängen durchgeführt, um kein fingiertes \fBSIGSTOP\fP einzuleiten.) Ab Linux 3.2.9 werden die folgenden Systemaufrufe beeinflusst (diese Liste ist wahrscheinlich nicht vollständig): \fBepoll_wait\fP(2) und \fBread\fP(2) von einem \fBinotify\fP(7)\-Dateideskriptor. Das übliche Anzeichen für diesen Fehler ist, falls Sie einen ruhenden Prozess mit dem Befehl strace \-p anhängen, dass Sie statt der erwarteten einzeilige Ausgabe, wie .nf restart_syscall(<... resuming interrupted call ...>_ .fi oder .nf select(6, [5], NULL, [5], NULL_ .fi ('_' kennzeichnet die Cursor\-Position) mehr als eine Zeile beobachten können, zum Beispiel: .nf clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0 epoll_wait(4,_ .fi Was hier nicht sichtbar ist, ist, dass der Prozess in \fBepoll_wait\fP(2) blockiert wurde, bevor \fBstrace\fP(1) an ihn angehängt hat. Das Anhängen verursachte ein \fBepoll_wait\fP(2), um zum User\-Space mit dem Fehler \fBEINTR\fP zurückzukehren. In diesem besonderen Fall reagiert das Programm auf \fBEINTR\fP, indem die aktuelle Zeit geprüft und dann \fBepoll_wait\fP(2) erneut ausgeführt wird. (Programme, die keine derartigen »verirrten« \fBEINTR\fP\-Fehler erwarten, können sich bei einem \fBstrace\fP(1)\-Anhängen in unbeabsichtigter Weise verhalten.) .SH "SIEHE AUCH" \fBgdb\fP(1), \fBstrace\fP(1), \fBclone\fP(2), \fBexecve\fP(2), \fBfork\fP(2), \fBgettid\fP(2), \fBsigaction\fP(2), \fBtgkill\fP(2), \fBvfork\fP(2), \fBwaitpid\fP(2), \fBexec\fP(3), \fBcapabilities\fP(7), \fBsignal\fP(7) .SH KOLOPHON Diese Seite ist Teil der Veröffentlichung 3.74 des Projekts Linux\-\fIman\-pages\fP. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden sich unter \%http://www.kernel.org/doc/man\-pages/. .SH ÜBERSETZUNG Die deutsche Übersetzung dieser Handbuchseite wurde von Patrick Rother , Chris Leick , Helge Kreutzmann und Mario Blättermann erstellt. Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen. Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an .