PTRACE(2) | System Calls Manual | PTRACE(2) |
ptrace
— process
tracing and debugging
Standard C Library (libc, -lc)
#include
<sys/types.h>
#include <sys/ptrace.h>
int
ptrace
(int
request, pid_t pid,
caddr_t addr,
int data);
The
ptrace
()
system call provides tracing and debugging facilities. It allows one process
(the
tracing
process) to control another (the
traced
process). The tracing process must first attach to the traced process, and
then issue a series of ptrace
() system calls to
control the execution of the process, as well as access process memory and
register state. For the duration of the tracing session, the traced process
will be “re-parented”, with its parent process ID (and
resulting behavior) changed to the tracing process. It is permissible for a
tracing process to attach to more than one other process at a time. When the
tracing process has completed its work, it must detach the traced process;
if a tracing process exits without first detaching all processes it has
attached, those processes will be killed.
Most of the time, the traced process runs normally,
but when it receives a signal (see sigaction(2)), it
stops. The tracing process is expected to notice this via
wait(2) or the delivery of a
SIGCHLD
signal, examine the state of the stopped
process, and cause it to terminate or continue as appropriate. The signal
may be a normal process signal, generated as a result of traced process
behavior, or use of the kill(2) system call;
alternatively, it may be generated by the tracing facility as a result of
attaching, stepping by the tracing process, or an event in the traced
process. The tracing process may choose to intercept the signal, using it to
observe process behavior (such as SIGTRAP
), or
forward the signal to the process if appropriate. The
ptrace
()
system call is the mechanism by which all this happens.
A traced process may report additional signal stops corresponding
to events in the traced process. These additional signal stops are reported
as SIGTRAP
or SIGSTOP
signals. The tracing process can use the PT_LWPINFO
request to determine which events are associated with a
SIGTRAP
or SIGSTOP
signal.
Note that multiple events may be associated with a single signal. For
example, events indicated by the PL_FLAG_BORN
,
PL_FLAG_FORKED
, and
PL_FLAG_EXEC
flags are also reported as a system
call exit event (PL_FLAG_SCX
). The signal stop for a
new child process enabled via PTRACE_FORK
will
report a SIGSTOP
signal. All other additional signal
stops use SIGTRAP
.
Each traced process has a tracing event mask. An event in the traced process only reports a signal stop if the corresponding flag is set in the tracing event mask. The current set of tracing event flags include:
PTRACE_EXEC
PL_FLAG_EXEC
flag
in the pl_flags member of struct
ptrace_lwpinfo.PTRACE_SCE
PL_FLAG_SCE
flag in the
pl_flags member of struct
ptrace_lwpinfo.PTRACE_SCX
PL_FLAG_SCX
flag in the
pl_flags member of struct
ptrace_lwpinfo.PTRACE_SYSCALL
PTRACE_FORK
When this event flag is enabled, new child processes will
enable tracing and stop before executing their first instruction. The
new child process will include the PL_FLAG_CHILD
flag in the pl_flags member of
struct ptrace_lwpinfo. The traced process will
report a stop that includes the PL_FLAG_FORKED
flag. The process ID of the new child process will also be present in
the pl_child_pid member of struct
ptrace_lwpinfo. If the new child process was created via
vfork(2), the traced process's stop will also include
the PL_FLAG_VFORKED
flag. Note that new child
processes will be attached with the default tracing event mask; they do
not inherit the event mask of the traced process.
When this event flag is not enabled, new child processes will execute without tracing enabled.
PTRACE_LWP
PL_FLAG_BORN
set before executing their
first instruction, and exiting LWPs will stop and report an event with
PL_FLAG_EXITED
set before completing their
termination.
Note that new processes do not report an event for the creation of their initial thread, and exiting processes do not report an event for the termination of the last thread.
PTRACE_VFORK
When a thread in the traced process creates a new child
process via vfork(2), the stop that reports
PL_FLAG_FORKED
and
PL_FLAG_SCX
occurs just after the child process
is created, but before the thread waits for the child process to stop
sharing process memory. If a debugger is not tracing the new child
process, it must ensure that no breakpoints are enabled in the shared
process memory before detaching from the new child process. This means
that no breakpoints are enabled in the parent process either.
The PTRACE_VFORK
flag enables a new
stop that indicates when the new child process stops sharing the process
memory of the parent process. A debugger can reinsert breakpoints in the
parent process and resume it in response to this event. This event is
indicated by setting the PL_FLAG_VFORK_DONE
flag.
The default tracing event mask when attaching to a process via
PT_ATTACH
, PT_TRACE_ME
, or
PTRACE_FORK
includes only
PTRACE_EXEC
events. All other event flags are
disabled.
The request argument specifies
what operation is being performed; the meaning of the rest of the arguments
depends on the operation, but except for one special case noted below, all
ptrace
()
calls are made by the tracing process, and the pid
argument specifies the process ID of the traced process or a corresponding
thread ID. The request argument can be:
PT_TRACE_ME
ptrace
().) When a process has used this request
and calls execve(2) or any of the routines built on it
(such as execv(3)), it will stop before executing the
first instruction of the new image. Also, any setuid or setgid bits on the
executable being executed will be ignored. If the child was created by
vfork(2) system call or rfork(2) call
with the RFMEM
flag specified, the debugging
events are reported to the parent only after the
execve(2) is executed.PT_READ_I
,
PT_READ_D
ptrace
() has allowed for machines with distinct
address spaces for instruction and data, which is why there are two
requests: conceptually, PT_READ_I
reads from the
instruction space and PT_READ_D
reads from the
data space. In the current FreeBSD implementation,
these two requests are completely identical. The
addr argument specifies the address (in the traced
process's virtual address space) at which the read is to be done. This
address does not have to meet any alignment constraints. The value read is
returned as the return value from ptrace
().PT_WRITE_I
,
PT_WRITE_D
PT_READ_I
and
PT_READ_D
, except that they write rather than
read. The data argument supplies the value to be
written.PT_IO
struct ptrace_io_desc { int piod_op; /* I/O operation */ void *piod_offs; /* child offset */ void *piod_addr; /* parent offset */ size_t piod_len; /* request length */ }; /* * Operations in piod_op. */ #define PIOD_READ_D 1 /* Read from D space */ #define PIOD_WRITE_D 2 /* Write to D space */ #define PIOD_READ_I 3 /* Read from I space */ #define PIOD_WRITE_I 4 /* Write to I space */
The data argument is ignored. The actual number of bytes read or written is stored in piod_len upon return.
PT_CONTINUE
PT_STEP
PT_KILL
PT_CONTINUE
had been used with SIGKILL
given as the signal to
be delivered.PT_ATTACH
PT_DETACH
PT_GETREGS
<machine/reg.h>
) pointed
to by addr.PT_SETREGS
PT_GETREGS
; it
loads the traced process's machine registers from the
“struct reg” (defined in
<machine/reg.h>
) pointed
to by addr.PT_GETFPREGS
<machine/reg.h>
) pointed
to by addr.PT_SETFPREGS
PT_GETFPREGS
; it
loads the traced process's floating-point registers from the
“struct fpreg” (defined in
<machine/reg.h>
) pointed
to by addr.PT_GETDBREGS
<machine/reg.h>
) pointed
to by addr.PT_SETDBREGS
PT_GETDBREGS
; it
loads the traced process's debug registers from the
“struct dbreg” (defined in
<machine/reg.h>
) pointed
to by addr.PT_LWPINFO
struct ptrace_lwpinfo { lwpid_t pl_lwpid; int pl_event; int pl_flags; sigset_t pl_sigmask; sigset_t pl_siglist; siginfo_t pl_siginfo; char pl_tdname[MAXCOMLEN + 1]; pid_t pl_child_pid; u_int pl_syscall_code; u_int pl_syscall_narg; };
The data argument is to be set to the size of the structure known to the caller. This allows the structure to grow without affecting older programs.
The fields in the struct ptrace_lwpinfo have the following meaning:
PL_EVENT_NONE
PL_EVENT_SIGNAL
PL_FLAG_SCE
PL_FLAG_SCX
PL_FLAG_EXEC
PL_FLAG_SCX
is set, this flag may be
additionally specified to inform that the program being executed
by debuggee process has been changed by successful execution of a
system call from the
execve
(2)
family.PL_FLAG_SI
PL_FLAG_FORKED
fork
(2)
that created a new child process. The process identifier of the
new process is available in the pl_child_pid
member of struct ptrace_lwpinfo.PL_FLAG_CHILD
PTRACE_FORK
is
enabled.PL_FLAG_BORN
PTRACE_LWP
is enabled. It is reported
along with PL_FLAG_SCX
.PL_FLAG_EXITED
PTRACE_LWP
is enabled. Note that this
event is not reported when the last LWP in a process exits. The
termination of the last thread is reported via a normal process
exit event.PL_FLAG_VFORKED
PL_FLAG_FORKED
.PL_FLAG_VFORK_DONE
PL_EVENT_SIGNAL
stop when
PL_FLAG_SI
is set in
pl_flags.PL_EVENT_SIGNAL
stop when
PL_FLAG_FORKED
is set in
pl_flags.PL_FLAG_SCE
or
PL_FLAG_SCX
is set in
pl_flags.PL_FLAG_SCE
or
PL_FLAG_SCX
is set in
pl_flags.PT_GETNUMLWPS
PT_GETLWPLIST
ptrace
() is the count of array entries filled
in.PT_SETSTEP
PT_CLEARSTEP
PT_SUSPEND
PT_RESUME
PT_TO_SCE
PTRACE_SCE
event flag to
trace all future system call entries and continue the process. The
addr and data arguments are
used the same as for PT_CONTINUE.
PT_TO_SCX
PTRACE_SCX
event flag to
trace all future system call exits and continue the process. The
addr and data arguments are
used the same as for PT_CONTINUE.
PT_SYSCALL
PTRACE_SYSCALL
event
flag to trace all future system call entries and exits and continue the
process. The addr and data
arguments are used the same as for
PT_CONTINUE.
PT_GET_SC_ARGS
PL_FLAG_SCE
or PL_FLAG_SCX
state, that is, on entry or exit to a syscall, this request fetches the
syscall arguments.
The arguments are copied out into the buffer pointed to by the addr pointer, sequentially. Each syscall argument is stored as the machine word. Kernel copies out as many arguments as the syscall accepts, see the pl_syscall_narg member of the struct ptrace_lwpinfo, but not more than the data bytes in total are copied.
PT_FOLLOW_FORK
PTRACE_FORK
is set in the traced process's event
tracing mask. If data is zero,
PTRACE_FORK
is cleared from the traced process's
event tracing mask.PT_LWP_EVENTS
PTRACE_LWP
is set in the traced process's event tracing mask. If
data is zero, PTRACE_LWP
is
cleared from the traced process's event tracing mask.PT_GET_EVENT_MASK
PT_SET_EVENT_MASK
PT_VM_TIMESTAMP
ptrace
().
This provides a low-cost way for the tracing process to determine if the
VM map changed since the last time this request was made.PT_VM_ENTRY
struct ptrace_vm_entry { int pve_entry; int pve_timestamp; u_long pve_start; u_long pve_end; u_long pve_offset; u_int pve_prot; u_int pve_pathlen; long pve_fileid; uint32_t pve_fsid; char *pve_path; };
The first entry is returned by setting pve_entry to zero. Subsequent entries are returned by leaving pve_entry unmodified from the value returned by previous requests. The pve_timestamp field can be used to detect changes to the VM map while iterating over the entries. The tracing process can then take appropriate action, such as restarting. By setting pve_pathlen to a non-zero value on entry, the pathname of the backing object is returned in the buffer pointed to by pve_path, provided the entry is backed by a vnode. The pve_pathlen field is updated with the actual length of the pathname (including the terminating null character). The pve_offset field is the offset within the backing object at which the range starts. The range is located in the VM space at pve_start and extends up to pve_end (inclusive).
The data argument is ignored.
PT_GETVFPREGS
VFP
machine state in the
buffer pointed to by addr.
The data argument is ignored.
PT_SETVFPREGS
VFP
machine state from the buffer
pointed to by addr.
The data argument is ignored.
PT_GETXMMREGS
FXSAVE
.
This request is only valid for i386 programs, both on native
32-bit systems and on amd64 kernels. For 64-bit amd64 programs, the XMM
state is reported as part of the FPU state returned by the
PT_GETFPREGS
request.
The data argument is ignored.
PT_SETXMMREGS
FXRSTOR
.
As with PT_GETXMMREGS,
this request is
only valid for i386 programs.
The data argument is ignored.
PT_GETXSTATE_INFO
struct ptrace_xstate_info { uint64_t xsave_mask; uint32_t xsave_len; };
xsave_mask
field is a bitmask of the currently
enabled extensions. The meaning of the bits is defined in the Intel and
AMD processor documentation. The xsave_len
field
reports the length of the XSAVE area for storing the hardware state for
currently enabled extensions in the format defined by the x86
XSAVE
machine instruction.
The data argument value must be equal to the size of the struct ptrace_xstate_info.
PT_GETXSTATE
XSAVE
machine instruction.PT_SETXSTATE
xsave_len
field from the
struct ptrace_xstate_info of the
PT_GETXSTATE_INFO
request. Layout of the buffer is
identical to the layout of the load area for the
XRSTOR
machine instruction.PT_GETFSBASE
The data argument is ignored.
PT_GETGSBASE
PT_GETFSBASE
request, but returns the
base for the %gs segment register.PT_SETFSBASE
The data argument is ignored.
PT_SETGSBASE
PT_SETFSBASE
request, but sets the base
for the %gs segment register.PT_GETVRREGS
ALTIVEC
machine state in the
buffer pointed to by addr.
The data argument is ignored.
PT_SETVRREGS
ALTIVEC
machine state from the
buffer pointed to by addr.
The data argument is ignored.
PT_GETVSRREGS
VSX
registers
VSR0-VSR31 in the buffer pointed to by addr.
The data argument is ignored.
PT_SETVSRREGS
VSX
registers
VSR0-VSR31 from the buffer pointed to by addr.
The data argument is ignored.
Additionally, other machine-specific requests can exist.
Most requests return 0 on success and -1 on error. Some requests
can cause ptrace
() to return -1 as a non-error
value, among them are PT_READ_I
and
PT_READ_D
, which return the value read from the
process memory on success. To disambiguate, errno can
be set to 0 before the call and checked afterwards.
The current ptrace
() implementation always
sets errno to 0 before calling into the kernel, both
for historic reasons and for consistency with other operating systems. It is
recommended to assign zero to errno explicitly for
forward compatibility.
The ptrace
() system call may fail if:
ESRCH
]EINVAL
]PT_ATTACH
on
itself.PT_CONTINUE
was neither 0 nor a legal signal
number.PT_GETREGS
,
PT_SETREGS
,
PT_GETFPREGS
,
PT_SETFPREGS
,
PT_GETDBREGS
, or
PT_SETDBREGS
was attempted on a process with
no valid register set. (This is normally true only of system
processes.)PT_VM_ENTRY
was given an invalid value for pve_entry. This
can also be caused by changes to the VM map of the process.PT_LWPINFO
was less than or equal to zero, or
larger than the ptrace_lwpinfo structure known
to the kernel.PT_GETXSTATE_INFO
request was not equal to the
size of the struct ptrace_xstate_info.PT_SETXSTATE
request was less than the size of
the x87 plus the XMM save area.PT_SETXSTATE
request was larger than returned
in the xsave_len
member of the
struct ptrace_xstate_info from the
PT_GETXSTATE_INFO
request.PT_SETFSBASE
or
PT_SETGSBASE
, pointed outside of the valid
user address space. This error will not occur in 32-bit programs.EBUSY
]PT_ATTACH
was attempted on a process that was already being traced.PT_ATTACH
) specified a
process that was not stopped.EPERM
]PT_ATTACH
) attempted to
manipulate a process that was not being traced at all.PT_ATTACH
on a
process in violation of the requirements listed under
PT_ATTACH
above.ENOENT
]PT_VM_ENTRY
previously returned the last entry of the memory map. No more entries
exist.ENAMETOOLONG
]PT_VM_ENTRY
cannot return the pathname of the backing object because the buffer is
not big enough. pve_pathlen holds the minimum
buffer size required on return.execve(2), sigaction(2), wait(2), execv(3), i386_clr_watch(3), i386_set_watch(3)
The ptrace
() function appeared in
Version 6 AT&T UNIX.
June 2, 2018 | Debian |