Synopsis

#include <sys/ptrace.h>

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

Description

Theptrace() system call provides a means bywhich one process (the "tracer") may observe and control theexecution of another process (the "tracee"), and examine and changethe tracee'smemory and registers. It is primarily used toimplement breakpoint debugging and system call tracing.

A tracee first needs to be attachedto the tracer. Attachment and subsequent commands are per thread: in amultithreaded process, every thread can be individually attached to a(potentially different) tracer, or left not attached and thus not debugged.Therefore, "tracee" always means "(one) thread", never "a (possibly multithreaded) process". Ptrace commands are alwayssent to a specific tracee using a call of the form

ptrace(PTRACE_foo, pid, ...)

wherepidis the thread ID of the corresponding Linux thread.

(Note that in this page, a "multithreaded process" means athread group consisting of threads created using theclone(2)CLONE_THREADflag.)

A process can initiate a trace by callingfork(2)andhaving the resulting child do aPTRACE_TRACEME, followed(typically) by anexecve(2). Alternatively, oneprocess may commence tracing another process usingPTRACE_ATTACHorPTRACE_SEIZE.

While being traced, the tracee will stop each time a signal is delivered,even if the signal is being ignored. (An exception isSIGKILL, which hasits usual effect.) The tracer will be notified at its next call towaitpid(2)(orone of the related "wait" system calls); that call will returnastatusvalue containing information that indicates the causeof the stop in the tracee. While the tracee is stopped, the tracer can usevarious ptrace requests to inspect and modify the tracee. The tracer thencauses the tracee to continue, optionally ignoring the delivered signal (oreven delivering a different signal instead).

If thePTRACE_O_TRACEEXECoption is not in effect, allsuccessful calls toexecve(2)by the tracedprocess will cause it to be sent aSIGTRAPsignal, giving theparent a chance to gain control before the new program begins execution.

When the tracer is finished tracing, it can cause the tracee to continueexecuting in a normal, untraced mode viaPTRACE_DETACH.

The value ofrequestdeterminesthe action to be performed:

PTRACE_TRACEME

Indicate that thisprocess is to be traced by its parent. A process probably shouldn't make thisrequest if its parent isn't expecting to trace it. (pid,addr,anddataare ignored.)

ThePTRACE_TRACEMErequest is used only by the tracee;the remaining requests are used only by the tracer. In the followingrequests,pidspecifies the thread ID of the tracee to be actedon. For requests other thanPTRACE_ATTACH,PTRACE_SEIZE,PTRACE_INTERRUPTandPTRACE_KILL,the tracee must be stopped.

PTRACE_PEEKTEXT,PTRACE_PEEKDATA

Read a word at theaddressaddrin the tracee's memory, returning the word as theresult of theptrace() call. Linux does not have separate text anddata address spaces, so these two requests are currently equivalent. (dataisignored.)

PTRACE_PEEKUSER

Read a word atoffsetaddrin the tracee's USER area, which holds theregisters and other information about the process (see<sys/user.h>).The word is returned as the result of theptrace() call. Typically,the offset must be word-aligned, though this might vary by architecture. SeeNOTES. (datais ignored.)

PTRACE_POKETEXT,PTRACE_POKEDATA

Copy the worddatatothe addressaddrin the tracee's memory. As forPTRACE_PEEKTEXTandPTRACE_PEEKDATA,these two requests are currently equivalent.

PTRACE_POKEUSER

Copy the worddatatooffsetaddrin the tracee's USER area. As forPTRACE_PEEKUSER,the offset must typically be word-aligned. In order to maintain the integrityof the kernel, some modifications to the USER area are disallowed.

PTRACE_GETREGS,PTRACE_GETFPREGS

Copy the tracee'sgeneral-purpose or floating-point registers, respectively, to the addressdatainthe tracer. See<sys/user.h>for information on theformat of this data. (addris ignored.) Note that SPARC systemshave the meaning ofdataandaddrreversed; thatis,datais ignored and the registers are copied to theaddressaddr.PTRACE_GETREGSandPTRACE_GETFPREGSarenot present on all architectures.

PTRACE_GETREGSET(since Linux 2.6.34)

Read the tracee'sregisters.addrspecifies, in an architecture-dependent way,the type of registers to be read.NT_PRSTATUS(with numerical value1) usually results in reading of general-purpose registers. If the CPU has, forexample, floating-point and/or vector registers, they can be retrieved bysettingaddrto the correspondingNT_fooconstant.datapointsto astruct iovec, which describes the destination buffer'slocation and length. On return, the kernel modifiesiov.lentoindicate the actual number of bytes returned.

PTRACE_GETSIGINFO(since Linux 2.3.99-pre6)

Retrieve informationabout the signal that caused the stop. Copy asiginfo_tstructure(seesigaction(2)) from the traceeto the addressdatain the tracer. (addrisignored.)

PTRACE_SETREGS,PTRACE_SETFPREGS

Modify the tracee'sgeneral-purpose or floating-point registers, respectively, from theaddressdatain the tracer. As forPTRACE_POKEUSER, somegeneral-purpose register modifications may be disallowed. (addrisignored.) Note that SPARC systems have the meaning ofdataandaddrreversed;that is,datais ignored and the registers are copied from theaddressaddr.PTRACE_SETREGSandPTRACE_SETFPREGSarenot present on all architectures.

PTRACE_SETREGSET(since Linux 2.6.34)

Modify the tracee'sregisters. The meaning ofaddranddataisanalogous toPTRACE_GETREGSET.

PTRACE_SETSIGINFO(since Linux 2.3.99-pre6)

Set signalinformation: copy asiginfo_tstructure from the addressdatainthe tracer to the tracee. This will affect only signals that would normally bedelivered to the tracee and were caught by the tracer. It may be difficult totell these normal signals from synthetic signals generated byptrace()itself. (addris ignored.)

PTRACE_SETOPTIONS(since Linux 2.4.6; see BUGS forcaveats)

Set ptrace optionsfromdata. (addris ignored.)dataisinterpreted as a bit mask of options。

PTRACE_O_EXITKILL(since Linux 3.8)

If a tracer sets thisflag, aSIGKILLsignal will be sent to every tracee if the tracerexits. This option is useful for ptrace jailers that want to ensure thattracees can never escape the tracer's control.

PTRACE_O_TRACECLONE(since Linux 2.5.46)

Stop the tracee atthe nextclone(2)and automaticallystart tracing the newly cloned process, which will start with aSIGSTOP.Awaitpid(2)

by the tracer will return astatusvalue such that

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

The PID of the newprocess can be retrieved withPTRACE_GETEVENTMSG.

This option may not catch

clone(2)calls in all cases. If the tracee callsclone(2)withtheCLONE_VFORKflag,PTRACE_EVENT_VFORKwillbe delivered instead ifPTRACE_O_TRACEVFORKis set; otherwiseif the tracee callsclone(2)with the exitsignal set toSIGCHLD,PTRACE_EVENT_FORKwill bedelivered ifPTRACE_O_TRACEFORKis set.

PTRACE_O_TRACEEXEC(since Linux 2.5.46)

Stop the tracee atthe nextexecve(2). Awaitpid(2)bythe tracer will return astatus

value such that

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

If the execing threadis not a thread group leader, the thread ID is reset to thread group leader'sID before this stop. Since Linux 3.0, the former thread ID can be retrievedwithPTRACE_GETEVENTMSG.

PTRACE_O_TRACEEXIT(since Linux 2.5.60)

Stop the tracee atexit. Awaitpid(2)by the tracerwill return

astatusvalue such that

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

The tracee's exit statuscan be retrieved withPTRACE_GETEVENTMSG.

The tracee is stopped early during process exit,

when registers arestill available, allowing the tracer to see where the exit occurred, whereasthe normal exit notification is done after the process is finished exiting.Even though context is available, the tracer cannot prevent the exit fromhappening at this point.

PTRACE_O_TRACEFORK(since Linux 2.5.46)

Stop the tracee atthe nextfork(2)and automaticallystart tracing the newly forked process, which will start with aSIGSTOP.Awaitpid(2)by the tracerwill return

astatusvalue such that

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

The PID of the newprocess can be retrieved withPTRACE_GETEVENTMSG.

PTRACE_O_TRACESYSGOOD(since Linux 2.4.6)

When deliveringsystem call traps, set bit 7 in the signal number (i.e., deliverSIGTRAP|0x80).This makes it easy for the tracer to distinguish normal traps from those causedby a system call. (PTRACE_O_TRACESYSGOODmay not work on allarchitectures.)

PTRACE_O_TRACEVFORK(since Linux 2.5.46)

Stop the tracee atthe nextvfork(2)and automaticallystart tracing the newly vforked process, which will start with aSIGSTOP.Awaitpid(2)by

the tracer will return astatusvalue such that

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

The PID of the newprocess can be retrieved withPTRACE_GETEVENTMSG.

PTRACE_O_TRACEVFORKDONE(since Linux 2.5.60)

Stop the tracee atthe completion of the nextvfork(2). Awaitpid(2)bythe tracer will return astatusvalue such that

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

The PID of the newprocess can (since Linux 2.6.18) be retrieved withPTRACE_GETEVENTMSG.

PTRACE_GETEVENTMSG(since Linux 2.5.46)

Retrieve a message(as anunsigned long) about the ptrace event that just happened,placing it at the addressdatain the tracer. ForPTRACE_EVENT_EXIT,this is the tracee's exit status. ForPTRACE_EVENT_FORK,PTRACE_EVENT_VFORK,PTRACE_EVENT_VFORK_DONE,andPTRACE_EVENT_CLONE, this is the PID of the new process. (addrisignored.)

PTRACE_CONT

Restart the stoppedtracee process. Ifdatais nonzero, it is interpreted as thenumber of a signal to be delivered to the tracee; otherwise, no signal isdelivered. Thus, for example, the tracer can control whether a signal sent tothe tracee is delivered or not. (addris ignored.)

PTRACE_SYSCALL,PTRACE_SINGLESTEP

Restart the stoppedtracee as forPTRACE_CONT, but arrange for the tracee to be stoppedat the next entry to or exit from a system call, or after execution of a singleinstruction, respectively. (The tracee will also, as usual, be stopped uponreceipt of a signal.) From the tracer's perspective, the tracee will appear tohave been stopped by receipt of aSIGTRAP. So, forPTRACE_SYSCALL,for example, the idea is to inspect the arguments to the system call at thefirst stop, then do anotherPTRACE_SYSCALLand inspect thereturn value of the system call at the second stop. Thedataargumentis treated as forPTRACE_CONT. (addris ignored.)

PTRACE_SYSEMU,PTRACE_SYSEMU_SINGLESTEP(sinceLinux 2.6.14)

ForPTRACE_SYSEMU,continue and stop on entry to the next system call, which will not be executed.ForPTRACE_SYSEMU_SINGLESTEP, do the same but also singlestep if not asystem call. This call is used by programs like User Mode Linux that want toemulate all the tracee's system calls. Thedataargument istreated as forPTRACE_CONT. Theaddrargument isignored. These requests are currently supported only on x86.

PTRACE_LISTEN(since Linux 3.4)

Restart the stoppedtracee, but prevent it from executing. The resulting state of the tracee issimilar to a process which has been stopped by aSIGSTOP(orother stopping signal). See the "group-stop" subsection foradditional information.PTRACE_LISTENonly works on tracees attachedbyPTRACE_SEIZE.

PTRACE_KILL

Send the traceeaSIGKILLto terminate it. (addranddataareignored.)

Thisoperation is deprecated; do not use it!

Instead, send aSIGKILLdirectlyusingkill(2)ortgkill(2).The problem withPTRACE_KILLis that it requires the tracee tobe in signal-delivery-stop, otherwise it may not work (i.e., may completesuccessfully but won't kill the tracee). By contrast, sending aSIGKILLdirectlyhas no such limitation.

PTRACE_INTERRUPT(since Linux 3.4)

Stop a tracee. If thetracee is running, it will stop withPTRACE_EVENT_STOP. If thetracee is already stopped by a signal, or receives a signal in parallelwithPTRACE_INTERRUPT, it may report a group-stop or asignal-delivery-stop instead ofPTRACE_EVENT_STOP.PTRACE_INTERRUPTonlyworks on tracees attached byPTRACE_SEIZE.

PTRACE_ATTACH

Attach to the processspecified inpid, making it a tracee of the calling process. The traceeis sent aSIGSTOP, but will not necessarily have stopped by thecompletion of this call; usewaitpid(2)towait for the tracee to stop. See the "Attaching and detaching"subsection for additional information. (addranddataareignored.)

PTRACE_SEIZE(since Linux 3.4)

Attach to the processspecified inpid, making it a tracee of the calling process.UnlikePTRACE_ATTACH,PTRACE_SEIZEdoes not stop theprocess. Only aPTRACE_SEIZEd process can acceptPTRACE_INTERRUPTandPTRACE_LISTENcommands.addrmustbe zero.datacontains a bit mask of ptrace options toactivate immediately.

PTRACE_DETACH

Restart the stoppedtracee as forPTRACE_CONT, but first detach from it. Under Linux, atracee can be detached in this way regardless of which method was used toinitiate tracing. (addris ignored.)

Death under ptrace

When a (possibly multithreaded) process receives akilling signal (one whose disposition is set toSIG_DFLandwhose default action is to kill the process), all threads exit. Tracees reporttheir death to theirtracer(s). Notification of this event isdelivered via waitpid(2).

Note that the killing signal will first cause signal-delivery-stop (on onetracee only), and only after it is injected by the tracer (or after it wasdispatched to a thread which isn't traced), will death from the signal happenonalltracees within a multithreaded process. (The term"signal-delivery-stop" is explained below.)

SIGKILLdoes not generate signal-delivery-stopand therefore the tracer can't suppress it.SIGKILLkills evenwithin system calls (syscall-exit-stop is not generated prior to death bySIGKILL).The net effect is thatSIGKILLalways kills the process (allits threads), even if some threads of the process are ptraced.

When the tracee calls_exit(2), it reports its death to itstracer. Other threads are not affected.

When any thread executesexit_group(2),every tracee in its thread group reports its death to its tracer.

If thePTRACE_O_TRACEEXIToption is on,PTRACE_EVENT_EXITwillhappen before actual death. This applies to exits viaexit(2),exit_group(2),and signal deaths (exceptSIGKILL), and when threads are torn downonexecve(2)in amultithreaded process.

The tracer cannot assume that the ptrace-stopped tracee exists. There aremany scenarios when the tracee may die while stopped (such asSIGKILL).Therefore, the tracer must be prepared to handle anESRCHerroron any ptrace operation. Unfortunately, the same error is returned if thetracee exists but is not ptrace-stopped (for commands which require a stoppedtracee), or if it is not traced by the process which issued the ptrace call.The tracer needs to keep track of the stopped/running state of the tracee, andinterpretESRCHas "tracee died unexpectedly" onlyif it knows that the tracee has been observed to enter ptrace-stop. Note thatthere is no guarantee thatwaitpid(WNOHANG)will reliablyreport the tracee's death status if a ptrace operation returnedESRCH.waitpid(WNOHANG)mayreturn 0 instead. In other words, the tracee may be "not yet fullydead", but already refusing ptrace requests.

The tracer can't assume that the traceealwaysends itslife by reportingWIFEXITED(status)orWIFSIGNALED(status);there are cases where this does not occur. For example, if a thread other thanthread group leader does anexecve(2),it disappears; its PID will never be seen again, and any subsequent ptracestops will be reported under the thread group leader's PID.

Stopped states

A tracee can be in two states: running or stopped.

There are many kinds of states when the tracee is stopped, and in ptracediscussions they are often conflated. Therefore, it is important to use preciseterms.

In this manual page, any stopped state in which the tracee is ready toaccept ptrace commands from the tracer is calledptrace-stop.Ptrace-stops can be further subdivided intosignal-delivery-stop,group-stop,syscall-stop,and so on. These stopped states are described in detail below.

When the running tracee enters ptrace-stop, it notifies its tracerusingwaitpid(2)(or one of theother "wait" system calls). Most of this manual page assumes that thetracer waits with:

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

Ptrace-stopped tracees are reported as returns withpidgreaterthan 0 andWIFSTOPPED(status)true.

The__WALLflag does not include theWSTOPPEDandWEXITEDflags,but implies their functionality.

Setting theWCONTINUEDflag when callingwaitpid(2)isnot recommended: the "continued" state is per-process and consumingit can confuse the real parent of the tracee.

Use of theWNOHANGflag may causewaitpid(2)toreturn 0 ("no wait results available yet") even if the tracer knowsthere should be a notification. Example:

errno = 0;

ptrace(PTRACE_CONT, pid, 0L, 0L);

if (errno == ESRCH) {

/* tracee is dead */

r = waitpid(tracee, &status,__WALL | WNOHANG);

/* r can still be 0 here! */

}

The following kinds of ptrace-stops exist:signal-delivery-stops, group-stops,PTRACE_EVENTstops,syscall-stops. They all are reported bywaitpid(2)withWIFSTOPPED(status)true.They may be differentiated by examining the valuestatus>>8,and if there is ambiguity in that value, by queryingPTRACE_GETSIGINFO.(Note: theWSTOPSIG(status)macro can't be used to performthis examination, because it returns the value(status>>8) &0xff.)

Signal-delivery-stop

When a (possibly multithreaded) process receives anysignal exceptSIGKILL, the kernel selects an arbitrary thread whichhandles the signal. (If the signal is generated withtgkill(2),the target thread can be explicitly selected by the caller.) If the selectedthread is traced, it enters signal-delivery-stop. At this point, the signal isnot yet delivered to the process, and can be suppressed by the tracer. If thetracer doesn't suppress the signal, it passes the signal to the tracee in thenext ptrace restart request. This second step of signal delivery iscalledsignal injectionin this manual page. Note that if thesignal is blocked, signal-delivery-stop doesn't happen until the signal isunblocked, with the usual exception thatSIGSTOPcan't beblocked.

Signal-delivery-stop is observed by the tracer aswaitpid(2)returningwithWIFSTOPPED(status)true, with the signal returnedbyWSTOPSIG(status). If the signal isSIGTRAP, this maybe a different kind of ptrace-stop; see the "Syscall-stops" and"execve" sections below for details. IfWSTOPSIG(status)returnsa stopping signal, this may be a group-stop; see below.

Signal injection and suppression

After signal-delivery-stop is observed by the tracer, thetracer should restart the tracee with the call

ptrace(PTRACE_restart, pid, 0, sig)

wherePTRACE_restartis one of the restarting ptracerequests. Ifsigis 0, then a signal is not delivered.Otherwise, the signalsigis delivered. This operation iscalledsignal injectionin this manual page, to distinguish itfrom signal-delivery-stop.

Thesigvalue may be different from theWSTOPSIG(status)value:the tracer can cause a different signal to be injected.

Note that a suppressed signal still causes system calls to returnprematurely. In this case system calls will be restarted: the tracer will observethe tracee to reexecute the interrupted system call (orrestart_syscall(2)systemcall for a few syscalls which use a different mechanism for restarting) if thetracer usesPTRACE_SYSCALL. Even system calls (such aspoll(2))which are not restartable after signal are restarted after signal issuppressed; however, kernel bugs exist which cause some syscalls to failwithEINTReven though no observable signal is injected to thetracee.

Restarting ptrace commands issued in ptrace-stops other thansignal-delivery-stop are not guaranteed to inject a signal, even ifsigisnonzero. No error is reported; a nonzerosigmay simply beignored. Ptrace users should not try to "create a new signal" thisway: usetgkill(2)instead.

The fact that signal injection requests may be ignored when restarting thetracee after ptrace stops that are not signal-delivery-stops is a cause ofconfusion among ptrace users. One typical scenario is that the tracer observesgroup-stop, mistakes it for signal-delivery-stop, restarts the tracee with

ptrace(PTRACE_restart, pid, 0, stopsig)

with the intention of injectingstopsig, butstopsiggetsignored and the tracee continues to run.

TheSIGCONTsignal has a side effect of waking up (allthreads of) a group-stopped process. This side effect happens beforesignal-delivery-stop. The tracer can't suppress this side effect (it can onlysuppress signal injection, which only causes theSIGCONThandler tonot be executed in the tracee, if such a handler is installed). In fact, wakingup from group-stop may be followed by signal-delivery-stop forsignal(s)otherthanSIGCONT,if they were pending whenSIGCONTwas delivered. In otherwords,SIGCONTmay be not the first signal observed by thetracee after it was sent.

Stopping signals cause (all threads of) a process to enter group-stop.This side effect happens after signal injection, and therefore can besuppressed by the tracer.

In Linux 2.4 and earlier, theSIGSTOPsignal can't beinjected.

PTRACE_GETSIGINFOcan be used to retrieve asiginfo_tstructurewhich corresponds to the delivered signal.PTRACE_SETSIGINFOmay beused to modify it. IfPTRACE_SETSIGINFOhas been used toaltersiginfo_t, thesi_signofield and thesigparameterin the restarting command must match, otherwise the result is undefined.

Group-stop

When a (possibly multithreaded) process receives astopping signal, all threads stop. If some threads are traced, they enter agroup-stop. Note that the stopping signal will first cause signal-delivery-stop(on one tracee only), and only after it is injected by the tracer (or after itwas dispatched to a thread which isn't traced), will group-stop be initiatedonalltracees within the multithreaded process. As usual,every tracee reports its group-stop separately to the corresponding tracer.

Group-stop is observed by the tracer aswaitpid(2)returningwithWIFSTOPPED(status)true, with the stopping signalavailable viaWSTOPSIG(status). The same result is returned by someother classes of ptrace-stops, therefore the recommended practice is to performthe call

ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo)

The call can be avoided if the signal is notSIGSTOP,SIGTSTP,SIGTTIN,orSIGTTOU; only these four signals are stopping signals. If thetracer sees something else, it can't be a group-stop. Otherwise, the tracerneeds to callPTRACE_GETSIGINFO. IfPTRACE_GETSIGINFOfailswithEINVAL, then it is definitely a group-stop. (Other failurecodes are possible, such asESRCH("no such process") ifaSIGKILLkilled the tracee.)

As of Linux 2.6.38, after the tracer sees the tracee ptrace-stop and untilit restarts or kills it, the tracee will not run, and will not sendnotifications (exceptSIGKILLdeath) to the tracer, even ifthe tracer enters into anotherwaitpid(2)call.

The kernel behavior described in the previous paragraph causes a problemwith transparent handling of stopping signals. If the tracer restarts thetracee after group-stop, the stopping signal is effectively ignored--the traceedoesn't remain stopped, it runs. If the tracer doesn't restart the traceebefore entering into the nextwaitpid(2),futureSIGCONTsignals will not be reported to the tracer;this would cause theSIGCONTsignals to have no effect on thetracee.

Since Linux 3.4, there is a method to overcome this problem: insteadofPTRACE_CONT, aPTRACE_LISTENcommand can beused to restart a tracee in a way where it does not execute, but waits for anew event which it can report viawaitpid(2)(suchas when it is restarted by aSIGCONT).

PTRACE_EVENT stops

If the tracer setsPTRACE_O_TRACE_*options,the tracee will enter ptrace-stops calledPTRACE_EVENTstops.

PTRACE_EVENTstops are observed by the traceraswaitpid(2)returningwithWIFSTOPPED(status), andWSTOPSIG(status)returnsSIGTRAP.An additional bit is set in the higher byte of the status word: the valuestatus>>8willbe

(SIGTRAP | PTRACE_EVENT_foo << 8).

The following events exist:

PTRACE_EVENT_VFORK

Stop before returnfromvfork(2)orclone(2)withtheCLONE_VFORKflag. When the tracee is continued after thisstop, it will wait for child to exit/exec before continuing its execution (inother words, the usual behavior onvfork(2)).

PTRACE_EVENT_FORK

Stop before returnfromfork(2)orclone(2)withthe exit signal set toSIGCHLD.

PTRACE_EVENT_CLONE

Stop before returnfromclone(2).

PTRACE_EVENT_VFORK_DONE

Stop before returnfromvfork(2)orclone(2)withtheCLONE_VFORKflag, but after the child unblocked thistracee by exiting or execing.

For all four stops described above, the stop occurs in the parent (i.e.,the tracee), not in the newly created thread.PTRACE_GETEVENTMSGcanbe used to retrieve the new thread's ID.

PTRACE_EVENT_EXEC

Stop before returnfromexecve(2). Since Linux3.0,PTRACE_GETEVENTMSGreturns the former thread ID.

PTRACE_EVENT_EXIT

Stop before exit(including death fromexit_group(2)), signal death,or exit caused byexecve(2)in amultithreaded process.PTRACE_GETEVENTMSGreturns the exitstatus. Registers can be examined (unlike when "real" exit happens).The tracee is still alive; it needs to bePTRACE_CONTed orPTRACE_DETACHedto finish exiting.

PTRACE_EVENT_STOP

Stop induced byPTRACE_INTERRUPTcommand.

PTRACE_GETSIGINFOonPTRACE_EVENTstopsreturnsSIGTRAPinsi_signo, withsi_codesetto(event<<8) | SIGTRAP.

Syscall-stops

If the tracee was restarted byPTRACE_SYSCALL,the tracee enters syscall-enter-stop just prior to entering any system call. Ifthe tracer restarts the tracee withPTRACE_SYSCALL, the traceeenters syscall-exit-stop when the system call is finished, or if it isinterrupted by a signal. (That is, signal-delivery-stop never happens betweensyscall-enter-stop and syscall-exit-stop; it happensaftersyscall-exit-stop.)

Other possibilities are that the tracee may stop in aPTRACE_EVENTstop,exit (if it entered_exit(2) orexit_group(2)),be killed bySIGKILL, or die silently (if it is a thread groupleader, theexecve(2)happened inanother thread, and that thread is not traced by the same tracer; this situationis discussed later).

Syscall-enter-stop and syscall-exit-stop are observed by the traceraswaitpid(2)returningwithWIFSTOPPED(status)true, andWSTOPSIG(status)givingSIGTRAP.If thePTRACE_O_TRACESYSGOODoption was set by the tracer,thenWSTOPSIG(status)will give the value(SIGTRAP | 0x80).

Syscall-stops can be distinguished from signal-delivery-stop withSIGTRAPbyqueryingPTRACE_GETSIGINFOfor the following cases:

si_code<= 0

SIGTRAPwas delivered as a result of a user-space action, for example, asystem call (tgkill(2),kill(2),sigqueue(3),etc.), expiration of a POSIX timer, change of state on a POSIX message queue,or completion of an asynchronous I/O request.

si_code== SI_KERNEL (0x80)

SIGTRAPwas sent by the kernel.

si_code== SIGTRAP orsi_code==(SIGTRAP|0x80)

This is asyscall-stop.

However, syscall-stops happen very often (twice per system call), andperformingPTRACE_GETSIGINFOfor every syscall-stop may besomewhat expensive.

Some architectures allow the cases to be distinguished by examiningregisters. For example, on x86,rax== -ENOSYSinsyscall-enter-stop. SinceSIGTRAP(like any other signal)always happensaftersyscall-exit-stop, and at thispointraxalmost never contains -ENOSYS, theSIGTRAPlookslike "syscall-stop which is not syscall-enter-stop"; in other words,it looks like a "stray syscall-exit-stop" and can be detected thisway. But such detection is fragile and is best avoided.

Using thePTRACE_O_TRACESYSGOODoption is the recommendedmethod to distinguish syscall-stops from other kinds of ptrace-stops, since itis reliable and does not incur a performance penalty.

Syscall-enter-stop and syscall-exit-stop are indistinguishable from eachother by the tracer. The tracer needs to keep track of the sequence ofptrace-stops in order to not misinterpret syscall-enter-stop as syscall-exit-stopor vice versa. The rule is that syscall-enter-stop is always followed bysyscall-exit-stop,PTRACE_EVENTstop or the tracee's death; noother kinds of ptrace-stop can occur in between.

If after syscall-enter-stop, the tracer uses a restarting command otherthanPTRACE_SYSCALL, syscall-exit-stop is not generated.

PTRACE_GETSIGINFOon syscall-stops returnsSIGTRAPinsi_signo,withsi_codeset toSIGTRAPor(SIGTRAP|0x80).

PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP stops

[Details of these kinds of stops are yet to bedocumented.]

Informational and restarting ptrace commands

Most ptrace commands (all exceptPTRACE_ATTACH,PTRACE_SEIZE,PTRACE_TRACEME,PTRACE_INTERRUPT,andPTRACE_KILL) require the tracee to be in a ptrace-stop,otherwise they fail withESRCH.

When the tracee is in ptrace-stop, the tracer can read and write data tothe tracee using informational commands. These commands leave the tracee inptrace-stopped state:

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);

Note that some errors are not reported. For example,setting signal information (siginfo) may have no effect in someptrace-stops, yet the call may succeed (return 0 and not seterrno);queryingPTRACE_GETEVENTMSGmay succeed and return some randomvalue if current ptrace-stop is not documented as returning a meaningful eventmessage.

The call

ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);

affects one tracee. The tracee's current flags are replaced. Flags areinherited by new tracees created and "auto-attached" via activePTRACE_O_TRACEFORK,PTRACE_O_TRACEVFORK,orPTRACE_O_TRACECLONEoptions.

Another group of commands makes the ptrace-stopped tracee run. They havethe form:

ptrace(cmd, pid, 0, sig);

wherecmdisPTRACE_CONT,PTRACE_LISTEN,PTRACE_DETACH,PTRACE_SYSCALL,PTRACE_SINGLESTEP,PTRACE_SYSEMU,orPTRACE_SYSEMU_SINGLESTEP. If the tracee is insignal-delivery-stop,sigis the signal to be injected (if itis nonzero). Otherwise,sigmay be ignored. (When restarting atracee from a ptrace-stop other than signal-delivery-stop, recommended practiceis to always pass 0 insig.)

Attaching and detaching

A thread can be attached to the tracer using

the call

ptrace(PTRACE_ATTACH, pid, 0, 0);

or

ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags);

PTRACE_ATTACHsendsSIGSTOPto thisthread. If the tracer wants thisSIGSTOPto have no effect, itneeds to suppress it. Note that if other signals are concurrently sent to thisthread during attach, the tracer may see the tracee enter signal-delivery-stopwith othersignal(s) first! The usual practice is to reinject thesesignals untilSIGSTOPis seen, then suppressSIGSTOPinjection.The design bug here is that a ptrace attach and a concurrently deliveredSIGSTOPmayrace and the concurrentSIGSTOPmay be lost.

Since attaching sendsSIGSTOPand the tracer usuallysuppresses it, this may cause a strayEINTRreturn from thecurrently executing system call in the tracee, as described in the "Signalinjection and suppression" section.

Since Linux 3.4,PTRACE_SEIZEcan be used insteadofPTRACE_ATTACH.PTRACE_SEIZEdoes not stop theattached process. If you need to stop it after attach (or at any other time)without sending it any signals, usePTRACE_INTERRUPT command.

The request

ptrace(PTRACE_TRACEME, 0, 0, 0);

turns the calling thread into a tracee. The thread continues to run(doesn't enter ptrace-stop). A common practice is to follow thePTRACE_TRACEMEwith

raise(SIGSTOP);

and allow the parent (which is our tracer now) to observe oursignal-delivery-stop.

If thePTRACE_O_TRACEFORK,PTRACE_O_TRACEVFORK,orPTRACE_O_TRACECLONEoptions are in effect, then childrencreated by, respectively,vfork(2)orclone(2)withtheCLONE_VFORKflag,fork(2)orclone(2)withthe exit signal set toSIGCHLD, and other kinds ofclone(2),are automatically attached to the same tracer which traced their parent.SIGSTOPisdelivered to the children, causing them to enter signal-delivery-stop afterthey exit the system call which created them.

Detaching of the tracee is performed by:

ptrace(PTRACE_DETACH, pid, 0, sig);

PTRACE_DETACHis a restarting operation; therefore itrequires the tracee to be in ptrace-stop. If the tracee is insignal-delivery-stop, a signal can be injected. Otherwise, thesigparametermay be silently ignored.

If the tracee is running when the tracer wants to detach it, the usualsolution is to sendSIGSTOP(usingtgkill(2),to make sure it goes to the correct thread), wait for the tracee to stop insignal-delivery-stop forSIGSTOPand then detach it(suppressingSIGSTOPinjection). A design bug is that this can racewith concurrentSIGSTOPs. Another complication is that the traceemay enter other ptrace-stops and needs to be restarted and waited for again,untilSIGSTOPis seen. Yet another complication is to be surethat the tracee is not already ptrace-stopped, because no signal deliveryhappens while it is--not evenSIGSTOP.

If the tracer dies, all tracees are automatically detached and restarted,unless they were in group-stop. Handling of restart from group-stop iscurrently buggy, but the "as planned" behavior is to leave traceestopped and waiting forSIGCONT. If the tracee is restarted fromsignal-delivery-stop, the pending signal is injected.

execve(2)under ptrace

When one thread in a multithreaded process callsexecve(2),the kernel destroys all other threads in the process, and resets the thread IDof the execing thread to the thread group ID (process ID). (Or, to put thingsanother way, when a multithreaded process does anexecve(2),at completion of the call, it appears as though theexecve(2)occurredin the thread group leader, regardless of which thread did theexecve(2).)This resetting of the thread ID looks very confusing to tracers:

*

All other threadsstop inPTRACE_EVENT_EXITstop, if thePTRACE_O_TRACEEXIToptionwas turned on. Then all other threads except the thread group leader reportdeath as if they exited via_exit(2) with exit code 0.

*

The execing traceechanges its thread ID while it is in theexecve(2).(Remember, under ptrace, the "pid" returned fromwaitpid(2),or fed into ptrace calls, is the tracee's thread ID.) That is, the tracee'sthread ID is reset to be the same as its process ID, which is the same as thethread group leader's thread ID.

*

Then aPTRACE_EVENT_EXECstophappens, if thePTRACE_O_TRACEEXECoption was turned on.

*

If the thread groupleader has reported itsPTRACE_EVENT_EXITstop by this time,it appears to the tracer that the dead thread leader "reappears fromnowhere". (Note: the thread group leader does not report death viaWIFEXITED(status)untilthere is at least one other live thread. This eliminates the possibility thatthe tracer will see it dying and then reappearing.) If the thread group leaderwas still alive, for the tracer this may look as if thread group leader returnsfrom a different system call than it entered, or even "returned from asystem call even though it was not in any system call". If the thread groupleader was not traced (or was traced by a different tracer), then duringexecve(2)itwill appear as if it has become a tracee of the tracer of the execing tracee.

All of the above effects are the artifacts of the thread ID change in thetracee.

ThePTRACE_O_TRACEEXECoption is the recommended tool fordealing with this situation. First, it enablesPTRACE_EVENT_EXECstop,which occurs beforeexecve(2)returns. In thisstop, the tracer can usePTRACE_GETEVENTMSGto retrieve the tracee'sformer thread ID. (This feature was introduced in Linux 3.0). Second, thePTRACE_O_TRACEEXECoptiondisables legacySIGTRAPgeneration onexecve(2).

When the tracer receivesPTRACE_EVENT_EXECstopnotification, it is guaranteed that except this tracee and the thread groupleader, no other threads from the process are alive.

On receiving thePTRACE_EVENT_EXECstop notification, thetracer should clean up all its internal data structures describing the threadsof this process, and retain only one data structure--one which describes thesingle still running tracee, with

thread ID == thread group ID == process ID.

Example: two threads callexecve(2)atthe same time:

*** we get syscall-enter-stop in thread 1: **

PID1 execve("/bin/foo", "foo" <unfinished ...>

*** we issue PTRACE_SYSCALL for thread 1 **

*** we get syscall-enter-stop in thread 2: **

PID2 execve("/bin/bar", "bar" <unfinished ...>

*** we issue PTRACE_SYSCALL for thread 2 **

*** we get PTRACE_EVENT_EXEC for PID0, we issue PTRACE_SYSCALL **

*** we get syscall-exit-stop for PID0: **

PID0 <... execve resumed> ) = 0

If thePTRACE_O_TRACEEXECoptionisnotin effect for the execing tracee, the kernel deliversan extraSIGTRAPto the tracee afterexecve(2)returns.This is an ordinary signal (similar to one which can be generated bykill-TRAP), not a special kind of ptrace-stop. EmployingPTRACE_GETSIGINFOforthis signal returnssi_codeset to 0 (SI_USER). Thissignal may be blocked by signal mask, and thus may be delivered (much) later.

Usually, the tracer (for example,strace(1))would not want to show this extra post-execveSIGTRAPsignalto the user, and would suppress its delivery to the tracee (ifSIGTRAPisset toSIG_DFL, it is a killing signal). However, determiningwhichSIGTRAPto suppress is not easy. Setting thePTRACE_O_TRACEEXECoptionand thus suppressing this extraSIGTRAPis the recommendedapproach.

Real parent

The ptrace API (ab) uses the standard UNIX parent/childsignaling overwaitpid(2). This used to causethe real parent of the process to stop receiving several kinds ofwaitpid(2)notificationswhen the child process is traced by some other process.

Many of these bugs have been fixed, but as of Linux 2.6.38 several stillexist; see BUGS below.

As of Linux 2.6.38, the following is believed to work correctly:

*

exit/death by signalis reported first to the tracer, then, when the tracer consumes thewaitpid(2)result,to the real parent (to the real parent only when the whole multithreadedprocess exits). If the tracer and the real parent are the same process, thereport is sent only once.

Return Value

On success,PTRACE_PEEK*requests returnthe requested data, while other requests return zero. On error, all requestsreturn -1, anderrnois set appropriately. Since the valuereturned by a successfulPTRACE_PEEK*request may be -1, thecaller must clearerrnobefore the call, and then check itafterward to determine whether or not an error occurred.

Errors

EBUSY

(i386 only) There wasan error with allocating or freeing a debug register.

EFAULT

There was an attemptto read from or write to an invalid area in the tracer's or the tracee'smemory, probably because the area wasn't mapped or accessible. Unfortunately,under Linux, different variations of this fault will returnEIOorEFAULTmore or less arbitrarily.

EINVAL

An attempt was madeto set an invalid option.

EIO

requestis invalid, or an attempt was made to read from or write to aninvalid area in the tracer's or the tracee's memory, or there was aword-alignment violation, or an invalid signal was specified during a restartrequest.

EPERM

The specified processcannot be traced. This could be because the tracer has insufficient privileges(the required capability isCAP_SYS_PTRACE); unprivileged processescannot trace processes that they cannot send signals to or those runningset-user-ID/set-group-ID programs, for obvious reasons. Alternatively, theprocess may already be being traced, or (on kernels before 2.6.26) beinit(8)(PID1).

ESRCH

The specified processdoes not exist, or is not currently being traced by the caller, or is notstopped (for requests that require a stopped tracee).

Conforming to

SVr4, 4.3BSD.

Notes

Although arguments toptrace() areinterpreted according to the prototype given, glibc currently declaresptrace()as a variadic function with only therequestargument fixed.It is recommended to always supply four arguments, even if the requestedoperation does not use them, setting unused/ignored arguments to0Lor(void*) 0.

In Linux kernels before 2.6.26,init(8),the process with PID 1, may not be traced.

The layout of the contents of memory and the USER area are quiteoperating-system- and architecture-specific. The offset supplied, and the datareturned, might not entirely match with the definition ofstruct user.

The size of a "word" is determined by the operating-systemvariant (e.g., for 32-bit Linux it is 32 bits).

This page documents the way theptrace() call works currentlyin Linux. Its behavior differs noticeably on other flavors of UNIX. In anycase, use ofptrace() is highly specific to the operating systemand architecture.

Bugs

On hosts with 2.6 kernel headers,PTRACE_SETOPTIONSisdeclared with a different value than the one for 2.4. This leads toapplications compiled with 2.6 kernel headers failing when run on 2.4 kernels.This can be worked around by redefining PTRACE_SETOPTIONStoPTRACE_OLDSETOPTIONS,if that is defined.

Group-stop notifications are sent to the tracer, but not to real parent.Last confirmed on 2.6.38.6.

If a thread group leader is traced and exits by calling_exit(2),aPTRACE_EVENT_EXITstop will happen for it (if requested),but the subsequentWIFEXITEDnotification will not bedelivered until all other threads exit. As explained above, if one of otherthreads callsexecve(2), the death of thethread group leader willneverbe reported. If the execedthread is not traced by this tracer, the tracer will never know thatexecve(2)happened.One possible workaround is toPTRACE_DETACHthe thread groupleader instead of restarting it in this case. Last confirmed on 2.6.38.6.

ASIGKILLsignal may still cause aPTRACE_EVENT_EXITstopbefore actual signal death. This may be changed in the future;SIGKILLismeant to always immediately kill tasks even under ptrace. Last confirmed on2.6.38.6.

Some system calls return withEINTRif a signal was sentto a tracee, but delivery was suppressed by the tracer. (This is very typicaloperation: it is usually done by debuggers on every attach, in order to notintroduce a bogusSIGSTOP). As of Linux 3.2.9, the following systemcalls are affected (this list is likely incomplete):epoll_wait(2),andread(2)from aninotify(7)filedescriptor. The usual

symptom of this bug is that when you attach to a quiescent process with

the command

strace -p <process-ID>

then, instead of the usual and expected one-line output such as

restart_syscall(<... resuming interrupted call ...>_

or

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

('_' denotes the cursor position), you observe more thanone line. For example:

clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0

epoll_wait(4,_

What is not visible here is that the process was blockedinepoll_wait(2)beforestrace(1)hasattached to it. Attaching caused epoll_wait(2)toreturn to user space with the errorEINTR. In this particular case,the program reacted toEINTRby checking the current time, andthen executingepoll_wait(2)again.(Programs which do not expect such "stray"EINTRerrorsmay behave in an unintended way upon anstrace(1)attach.)

更多相关文章

  1. 代码中设置drawableleft
  2. android 3.0 隐藏 系统标题栏
  3. Android开发中activity切换动画的实现
  4. Android(安卓)学习 笔记_05. 文件下载
  5. Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
  6. 技术博客汇总
  7. android 2.3 wifi (一)
  8. AndRoid Notification的清空和修改
  9. Android中的Chronometer

随机推荐

  1. 阅读Android消息机制源码的随手笔记
  2. Android(安卓)动画效果(一)
  3. android 使用android.support.v7 添加Act
  4. WebView中捕获JavaScript事件
  5. android marquee textview 走马灯效果
  6. 实现图片的圆角,倒影,转换
  7. Android:RelativeLayout 内容居中
  8. Android(安卓)Timer 分析
  9. STF本地集成-for-Mac
  10. Android-隐藏app图标以及隐式启动