int
ptrace(
int request
, pid_t pid
, void *addr
, int data
)
)
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.
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
).)
When a process has used this request and calls
execve(2)
or any of the routines built on it
execv(3)
(such as,)
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
NetBSD
implementation, these
two requests are completely identical.
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.
The
data
argument supplies the value to be written.
PT_CONTINUE
addr
is an address specifying the place where execution is to be resumed (a
new value for the program counter), or
(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
pid
specifies the process ID of the to-be-traced process, and the other two
arguments are ignored.
This request requires that the target process
must have the same real UID as the tracing process, and that it must
not be executing a setuid or setgid executable.
(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.
Three other restrictions apply to all tracing processes, even those running as root. First, no process may trace a system process. Second, no process may trace the process running init(8). Third, if a process has its root directory set with chroot(2), it may not trace another process unless that process's root directory is at or below the tracing process's root.
PT_DETACH
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
take place,
piod_addr
is the buffer in the tracing process, and
piod_len
is the length of the I/O request.
The
piod_op
field specifies which type of I/O operation to perform.
Possible
values are:
PIOD_READ_D
PIOD_WRITE_D
PIOD_READ_I
PIOD_WRITE_I
See the description of
PT_READ_I
for the difference between I and D spaces.
A pointer to the I/O descriptor is passed in the
addr
argument to
ptrace().
On return, the
piod_len
field in the I/O descriptor will be updated with the actual number of
bytes transferred.
If the requested I/O could not be successfully performed,
ptrace()
will return
-1
and set
errno.
PT_DUMPCORE
pid
pid generate a core dump.
The
addr
argument should contain the name of the core file to be generated
and the
data
argument should contain the length of the core filename.
This
ptrace
call currently does not stop the child process so it can generate
inconsistent data.
PT_LWPINFO
pid
argument.
The
addr
argument should contain a
``
struct ptrace_lwpinfo
''
defined as:
struct ptrace_lwpinfo {
lwpid_t pl_lwpid;
int pl_event;
};
where
pl_lwpid
contains the thread for which to get info.
Upon return
pl_event
contains the event that stopped the thread.
Possible
values are:
PL_EVENT_NONE
PL_EVENT_SIGNAL
The
data
argument should contain
``sizeof(struct ptrace_lwpinfo)
''.
PT_SYSCALL
Additionally, the following requests exist but are
not available on all machine architectures.
The file
<machine/ptrace.h
>
lists which requests exist on a given machine.
PT_STEP
PT_GETREGS
struct reg
''
(defined in
<
machine/reg.h
>)
pointed to by
addr
.
PT_SETREGS
PT_GETREGS
;
it loads the traced process' machine registers from the
``
struct reg
''
(defined in
<
machine/reg.h
>)
pointed to by
addr
.
PT_GETFPREGS
struct fpreg
''
(defined in
<
machine/reg.h
>)
pointed to by
addr
.
PT_SETFPREGS
PT_GETFPREGS
;
it loads the traced process' floating-point registers from the
``
struct fpreg
''
(defined in
<
machine/reg.h
>)
pointed to by
addr
.
PT_DUMPCORE
addr
argument is not
NULL
it is taken to be the pathname of the core file to be generated and the
data
argument should contain the length of the pathname.
The pathname may contain
%
patterns that are expanded as described in
sysctl(8).
If the
data
argument is
NULL
,
the default core file path generation rules are followed.
)
to return
-1
as a non-error value; to disambiguate,
errno
can be set to 0 before the call and checked afterwards.
The possible errors are:
EAGAIN
]
ESRCH
]
EINVAL
]
PT_ATTACH
on itself.
request
was not a legal request on this machine architecture.
data
)
to
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.
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_CONTINUE
and similar calls,
but the NPC is set willy-nilly to 4 greater than the PC value.
Using
PT_GETREGS
and
PT_SETREGS
to modify the PC, passing
(caddr_t)1
to
ptrace(
)
should be able to sidestep this.