PTRACE(2) | System Calls Manual | PTRACE(2) |
ptrace
— process
tracing and debugging
#include
<sys/types.h>
#include <sys/ptrace.h>
int
ptrace
(int
request, pid_t pid,
caddr_t addr,
int data);
ptrace
()
provides tracing and debugging facilities. It allows one process (the
tracing
process) to control another (the
traced
process). 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.
ptrace
() is the mechanism by which all this happens.
ptrace
() is only available on kernels compiled with
the PTRACE
option.
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.
request 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.PT_READ_I
,
PT_READ_D
int
of data from the
traced process' address space. Traditionally,
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 OpenBSD implementation,
these two requests operate in the same address space. The
addr argument specifies the address (in the traced
process' 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. PT_WRITE_I
may be necessary to ensure that
instruction caches are flushed appropriately. The
data argument supplies the value to be written.PT_CONTINUE
(caddr_t)1
to
indicate that execution is to pick up where it left off.
data provides a signal number to be delivered to the
traced process as it resumes execution, or 0 if no signal is to be
sent.PT_KILL
PT_CONTINUE
had been used with SIGKILL
given as the signal to
be delivered.PT_ATTACH
kern.global_ptrace
sysctl is 0, then the target
process must be a descendant of the tracing process. (If the tracing
process is running as root, these restrictions do not apply.) The tracing
process will see the newly traced process stop and may then control it as
if it had been traced all along.PT_DETACH
PT_CONTINUE
, except that it
does not allow specifying an alternate place to continue execution, and
after it succeeds, the traced process is no longer traced and continues
execution normally.PT_IO
PT_READ_D
, PT_WRITE_D
,
PT_READ_I
and PT_WRITE_I
.
The I/O request is encoded in a “struct
ptrace_io_desc
” defined as:
struct ptrace_io_desc { int piod_op; void *piod_offs; void *piod_addr; size_t piod_len; };
Where piod_offs is the offset within the traced process where the I/O operation should be made, piod_addr is the buffer in the parent and piod_len is the length of the I/O request. The piod_op member specifies what operation needs to be done. Possible values are:
See also the description of
PT_READ_I
for the difference between D and I
spaces. The PIOD_READ_AUXV
operation can be used
to read from the ELF auxiliary vector. A pointer to the descriptor is
passed in addr. On return the
piod_len field in the descriptor will be updated
with the actual number of bytes transferred. If the requested I/O
couldn't be successfully performed
ptrace
()
will return -1
and set
errno.
PT_SET_EVENT_MASK
struct ptrace_event
” defined as:
typedef struct ptrace_event { int pe_set_event; } ptrace_event_t;
Where pe_set_event is the set of events to be reported. This set is formed by OR'ing together the following values:
A pointer to this structure is passed in
addr. The data argument
should be set to sizeof(struct
ptrace_event)
.
PT_GET_EVENT_MASK
struct ptrace_event
” pointed to by
addr. The data argument should
be set to sizeof(struct ptrace_event)
.PT_GET_PROCESS_STATE
struct ptrace_state
” defined as:
typedef struct ptrace_state { int pe_report_event; pid_t pe_other_pid; } ptrace_state_t;
Where pe_report_event is the event being
reported. If the event being reported is
PTRACE_FORK
, pe_other_pid
will be set to the process ID of the other end of the fork. A pointer to
this structure is passed in addr. The
data argument should be set to
sizeof(struct ptrace_state)
.
PT_GET_THREAD_FIRST
struct ptrace_thread_state
”
pointed to by addr. The data
argument should be set to sizeof(struct
ptrace_thread_state)
.PT_GET_THREAD_NEXT
PT_GET_THREAD_FIRST
,
except it returns the thread ID of the subsequent thread. The
“struct ptrace_thread_state
” pointed
to by addr must be initialized by a previous
PT_GET_THREAD_FIRST
or
PT_GET_THREAD_NEXT
request.Additionally, machine-specific requests can exist. Depending on the architecture, the following requests may be available under OpenBSD:
PT_GETREGS
(all platforms)struct reg
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_SETREGS
(all platforms)PT_GETREGS
; it
loads the traced process' machine registers from the
“struct reg
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_STEP
(not available on sparc64)PT_CONTINUE
; however, execution stops as soon as
possible after execution of at least one instruction (single-step).PT_GETFPREGS
(not available on luna88k or sgi)struct fpreg
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_SETFPREGS
(not available on luna88k or sgi)PT_GETFPREGS
; it
loads the traced process' floating-point registers from the
“struct fpreg
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_GETXMMREGS
(i386 only)struct xmmregs
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_SETXMMREGS
(i386 only)PT_GETXMMREGS
; it
loads the traced process' XMM registers from the
“struct xmmregs
” (defined in
<machine/reg.h>
) pointed
to by addr.PT_WCOOKIE
(sparc64 only)int
pointed to by addr.
The window cookie needs to be ‘XOR'ed’ to stack-saved
program counters.Some requests can cause ptrace
() to return
-1
as a non-error value; to disambiguate,
errno is set to zero and this should be checked. The
possible errors are:
ESRCH
]EINVAL
]PT_ATTACH
on
itself.PT_CONTINUE
was neither 0 nor a legal signal
number.PT_GETREGS
,
PT_SETREGS
,
PT_GETFPREGS
, or
PT_SETFPREGS
was attempted on a process with
no valid register set. (This is normally true only of system
processes.)EBUSY
]PT_ATTACH
was attempted on a process that was already being traced.PT_ATTACH
) specified a
process that wasn't stopped and waited for.EPERM
]PT_ATTACH
) attempted to
manipulate a process that wasn't being traced at all.PT_ATTACH
on a
process in violation of the requirements listed under
PT_ATTACH
above.PT_ATTACH
on a
system process.The ptrace
() system call first appeared in
Version 6 AT&T UNIX.
On several RISC architectures (such as luna88k and sparc64), the
PC is set to the provided PC value for PT_CONTINUE
and similar calls, and the remainder of the execution pipeline registers are
set to the following instructions, even if the instruction at PC is a branch
instruction. Using PT_GETREGS
and
PT_SETREGS
to modify the PC, passing
(caddr_t)1
to ptrace
(),
should be able to sidestep this.
September 1, 2016 | OpenBSD-6.8 |