ttrace(2)ttrace(2)NAMEttrace() - tracing facility for multithreaded processes
SYNOPSIS
Remarks
While the POSIX API is defined and will not change, the present under‐
lying system calls are not guaranteed to be compatible with future ver‐
sions.
Much of the functionality of this capability is highly dependent on the
underlying hardware. An application that uses this system call should
not be expected to be portable across architectures or implementations.
DESCRIPTION
The system call provides a means by which a process can control the
execution of another process. Its primary use is for the implementa‐
tion of breakpoint and event driven debugging; see adb(1) and dde(1).
is designed to function for both single and multithreaded traced pro‐
cesses. The traced process behaves normally until one of its threads
encounters a signal (see signal(2) for the list), or an event (these
are discussed in detail in the section below) at which time the thread
enters a stopped state and the tracing process is notified via
Requests
Most of the requests are to be used only by the tracing process. How‐
ever, some requests (those suffixed by can be used by any process pro‐
vided that the effective user ID of the calling process matches the
real and saved uid of the target process. This is true unless the
calling process has the privilege.
requests are divided in four groups: requests that target a process,
requests that target a specific thread within the process, requests
that perform a series of requests on a process or thread, and non-
debug-related requests that target neither a process or a thread.
The request argument determines the action to be taken by and is one of
the following: For all process-wide requests (those prefixed by pid is
the process ID of the target process and lwpid must be set to zero.
This request must be issued by a child process
if it is to be traced by its parent.
The addr2 argument specifies the action to be taken by
the loader when the child process does an If the value
is the loader will communicate certain events to the
debugger through an architected break instruction. The
information obtained through these events can be used by
the debugger to identify all the load modules in the
program and their unwind information. If the debugger
is not interested in these events the value must be set
to 0 (zero).
The pid, lwpid, and addr arguments must be set to 0
(zero) and data must be set to Peculiar results occur if
the parent does not expect to trace the child.
Note: It is critical for future backward compatibility
that the macro itself be used and not its value.
This request allows the calling process to trace the process identified
by
pid. The process pid does not have to be a child of the
calling process, but the effective user ID of the call‐
ing process must match the real and saved uid of the
process pid unless the tracing process has the privi‐
lege.
When this call returns, the target process (all its
threads) is stopped.
The addr argument specifies the action to be taken if
the debugger exits without having detached the target
process. If the value is the attached process(es) will
be killed. If the value is the attached process(es)
will be resumed and detached as if the debugger had per‐
formed a request.
The addr2 argument specifies the action to be taken by
the loader when the target process does an If the value
is the loader will communicate certain events to the
debugger through an architected break instruction. The
information obtained through these events can be used by
the debugger to identify all the load modules in the
program and their unwind information. If the debugger
is not interested in these events the value must be set
to 0 (zero).
The lwpid argument must be set to zero and data must be
(see above).
This request is same as
except when this call returns, the target process is not
stopped (none of its threads are stopped).
This request detaches the traced process and allows it to continue
executing. It behaves identically to except that the
process is no longer being traced after the call
returns.
For this request, the lwpid, addr, data, and addr2 argu‐
ments must be set to zero.
These requests allow reading from the target process
text.
The addr argument specifies the offset to be read from.
The data argument specifies the number of bytes to read
and the addr2 argument specifies where to store that
data in the tracing process.
The lwpid argument must be set to zero.
These requests allow reading from the data space.
The addr argument specifies the offset to be read from.
The data argument specifies the number of bytes to read
and the addr2 argument specifies where to store that
data in the tracing process.
The lwpid argument must be set to zero.
These requests allow writing into the target process text
and data spaces
The addr argument specifies the offset to be written to.
The data argument specifies the number of bytes to
write.a The addr2 argument specifies where to get the
data in the tracing process.
The lwpid argument must be set to zero.
This request causes the traced process (all its threads) to stop.
If a thread was already stopped by the debugger prior to
this call, its state is not modified.
The lwpid, addr, data, and addr2 arguments must be set
to zero.
This request causes the entire traced process to resume execution.
All threads that had been stopped directly (request) or
indirectly (event) by the debugger are resumed with all
their pending signals intact.
The data, addr, and addr2 arguments must be set to zero.
This request is used by the calling process to access the path name of
the executable file provided as a path or file argument
to The request reads data bytes of data of the pathname
string from the traced process' context into the data
buffer in user space pointed to by addr.
In the typical case, data is equal to the value of the
ttexec_data_t.tts_len member of the structure returned
via the or other requests returning a Lightweight
Process (LWP or lwp) state. The length of the path does
not include a terminating null character. The data is
available during the entire life of the process.
The lwpid and addr2 arguments must be set to zero.
This request returns the process-wide event flags
and signal mask values.
The data argument specifies the number of bytes to be
read from the context of the traced process into the
data structure in user space pointed to by addr.
The lwpid and addr2 arguments must be set to zero.
The data structure is as follows:
The options provided in tte_opts control the behavior of
child processes produced by and are as follows:
If is set, the child process resulting from a will not
be traced. This makes it possible for a debugger to
debug another debugger. The and options allow events to
be inherited by child processes and threads respec‐
tively. Refer to the section below.
If is set, the SIGTRAP signal behaves normally. That
is, it is getting delivered (the default behavior is to
drop these signals).
This request allows the tracing process to establish
events and signals the traced process will respond to.
Refer to the section for a description of these events.
The addr argument is a pointer to a structure to be
copied into the target process. The data argument spec‐
ifies the number of bytes to be transferred.
The lwpid and addr2 arguments must be set to zero.
This request returns the process-wide signal mask value for
the target process that was set using
The data argument specifies the number of bytes to be
read from the context of the traced process into the
data structure in user space pointed by addr.
The lwpid and addr2 arguments must be set to zero.
The data structure is as follows:
The options provided in ttm_opts control the behavior of
signal masks on child processes produced by and are as
follows:
The and option allow signal masks to be inherited by
child processes and threads respectively.
This request allows the tracing process to change the signal
mask on the target process.
The addr argument is a pointer to a structure to be
copied into the target process. The data argument spec‐
ifies the number of bytes to be transferred.
The lwpid and addr2 arguments must be set to zero.
The resulting signal mask on the traced process will be
a union of the current signal mask on the target process
and the set pointed by the field in the structure. Set‐
ting the to an empty set results in clearing the signal
mask that was previously set using this request.
This request returns the
structure associated with the first thread on the
stopped list. It resets the list pointer to the first
entry in the list. The request (see below) provides the
means to examine the state of other stopped threads.
The data argument specifies the number bytes to be read
from the context of the traced process into the data
structure in the user space pointed to by addr. The
lwpid and addr2 arguments must be zero.
The structure provides the debugger with the means to
query the system for the state of a thread. It is
established when a thread enters the debugger stopped
state and, except for the bit, is invariant until the
thread is resumed. Its layout is as follows:
is the process ID.
is the lwpid of the stopped thread.
is the thread's user ID.
is the event that caused the stop if the thread stopped
because of a command).
The provide information about the state of the thread
before it was stopped. The information specifies
whether or not the thread has been waited for by whether
or not it is processing a system call, whether it is a
32-bit or a 64-bit process and whether the thread is in
the system call. The values are as follows:
The following three arguments provide information
regarding the system call being executed when the thread
was stopped. This information is valid only if the bit
is set in
is the system call number.
is the number of arguments of the system call.
is the argument list of the system call.
The data associated with a event is as follows:
is the length of the pathname of the system call.
The data associated with a or event is as follows:
is the process ID of the other side of the fork. This
field is set to zero for the event.
is the thread ID of the other side of the fork. This
field is set to zero for the event.
is zero for the child event and one for the parent.
is set to error code indicating the reason for error in
event. This field is set to zero for the and events.
The data associated with a event is as follows:
is the process ID of the other side of the fork.
is the thread ID of the other side of the fork.
is the type of fork.
The data associated with a event is as follows:
is the signal number.
is if a was delivered with the signal, 0 otherwise.
is the disposition of the signal.
is the if applicable.
The data associated with a or event is as follows:
is the lwpid of the targeted lwp.
The data associated with a event is as follows:
The fields are the return value(s) of the system call.
is the error status if the system call failed.
The data associated with a event is as follows:
is the exit code of the process.
The data associated with a event is as follows:
On PA-RISC systems:
is set to zero if it is a single-step and to one if the
event is a breakpoint (including single-stepping into a
breakpoint).
On systems:
This request is identical to
except that it returns the state for the next thread on
the stopped list. As events cause threads to stop, they
are added to this list. This provides a way for the
tracing process to examine the state of all the stopped
threads in the target process. Both these requests
return either a 1 (one) if valid data is returned or 0
(zero) otherwise. Valid data is returned if the status
is that there was a stopped thread for which to return.
This request allows the debugger to obtain protection information for
a page in the address space of the code being debugged.
The addr argument specifies the address for which the
protection is to be obtained. The addr2 argument speci‐
fies the address of an integer in which the protection
data will be copied.
For this request, the lwpid and data arguments must be
set to zero.
This requests allows the debugger to modify the protection of
the address space of the code being debugged. The addr
argument specifies the start address. The data argument
specifies the extent (in bytes) of the space to be modi‐
fied. The addr2 argument contains the new protection.
Note that protection changes affect whole pages (see
mprotect(2) for more information).
For this request, the lwpid argument must be set to
zero.
This request allows the debugger to pass a bitmap to the kernel
indicating which system calls should cause a debugger
stop.
The addr argument must be set to or to indicate whether
the bitmap represents a positive (meaning that the calls
in the bitmap will result in a stop) or a negative
(meaning that all calls except those in the bit map will
result in a stop) list.
The data argument is the size of the bitmap, in bytes.
A size of zero indicates that the current bitmap, if
any, should be cleared.
The addr2 argument is the user address where the bitmap
is located. If data is zero, this value must be zero
too.
The lwpid argument must be zero.
This request causes the traced process to terminate.
It has the same consequence as being invoked by one of
the process threads. The lwpid, addr, data, and addr2
arguments must be zero.
This request causes the traced process to generate a core file
without modifying the process's state. If addr is zero,
the core file is created in the target process's current
working directory and is named core.pid; where, pid is
the process ID of the target process. If addr is non-
zero, it is the address of a buffer containing the path
of the core file to be created. Up to bytes will be
read from the buffer. If the path is not absolute (not
starting with a slash), it is relative to the target
process's current working directory. In both cases, the
directory must exist and, if present, the file must be a
regular file. In all cases, the debugger's credentials
are used and standard permission checking applies. The
lwpid, data, and addr2 arguments must be zero.
Interaction with and If a process has a non-default core
file setting and addr is zero, then the core file will
be will be generated with the core file setting in
effect. If addr is a non-NULL value, then the core file
will be generated in the target path, as specified by
addr, and will be created as
These requests return the number of physical hardware instruction
or data breakpoint registers that are available for use.
These requests write process-wide breakpoint values into breakpoint
registers.
data bytes from addr2 will be written to the instruction
or data breakpoint register(s) named by addr. For Ita‐
nium-based systems, addr must be an even number less
than the value returned by or respectively. data must
be 16 bytes. The request will set a value into the pair
of instruction or data breakpoint registers addr and
addr+1.
Note: The available breakpoint registers must be shared
between process-wide breakpoints and per-thread break‐
points. If a breakpoint register is currently being
used as a per-thread breakpoint in any thread within the
target process, it may not be used for a process-wide
breakpoint.
Note: This does not limit the number of instructions
that may be present in the program text.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX.
These requests read process-wide breakpoint values from breakpoint reg‐
isters.
data bytes are copied from the instruction or data
breakpoint register(s) specified by addr to addr2 in
debugger memory. data must be 16 bytes. The request
will get the value of the pair of instruction or data
breakpoint registers addr and addr+1.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX.
These requests return a pointer to the argument list passed to the
initial thread of the process at time (that is, argc,
argv, envp). If the target process has not overwritten
these arguments, this address can be used to retrieve
the full argument and environment list.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX. For all thread requests (those prefixed
by pid is the process id of the target process and lwpid
is the target thread within the target process.
This request causes the thread identified by
lwpid to stop executing. If the thread is already
stopped or an error is returned.
The addr, data, and addr2 arguments must be zero.
This request causes the thread identified by
lwpid to resume execution or, rather, to return to the
state it was in prior to being stopped If the thread had
not previously been stopped by the debugger, an error is
returned.
If addr is not that value is loaded in the program
counter before execution is resumed. Unexpected behav‐
ior will result if this value is not within the same
function since only the PC, not the context, is being
modified.
If data is non-zero, it is expected to be a valid signal
number and the thread will continue as if it had
received this signal.
The addr2 argument must be zero.
This request causes the stopped thread identified by
lwpid to resume execution for one machine instruction.
It causes a flag to be set so that an interrupt occurs
upon the completion of one machine instruction, and then
executes the same steps as listed above for the request.
This request causes the stopped thread identified by
lwpid to resume execution until a taken branch instruc‐
tion is executed. It causes a flag to be set so that an
interrupt occurs upon completion of the next taken
branch instruction, and then executes the same steps as
listed above for the request.
Note: This request is not supported on PA-RISC versions
of HP-UX.
This request is the same as
except for the thread identified by lwpid.
This request is the same as
except for the thread identified by lwpid.
This request is the same as
except for the thread identified by lwpid.
This request is the same as
except for the thread identified by lwpid.
This calls returns the state of the thread identified by
lwpid. If the thread was not previously stopped by the
debugger or waiting to be continued after an event, an
error is returned.
These requests write per-thread breakpoint values into breakpoint reg‐
isters.
data bytes from addr2 will be written to the instruction
or data breakpoint register(s) named by addr. For Ita‐
nium-based systems, addr must be an even number less
than the value returned by or respectively. data must
be 16 bytes. The request will set a value into the pair
of instruction or data breakpoint registers addr and
addr+1. These values will be enabled only when the
specified thread is running. They are identical to and
respectively in other respects.
Note: The available breakpoint registers must be shared
between process-wide breakpoints and per-thread break‐
points. If a breakpoint register is currently being
used as a process-wide breakpoint within the target
process, it may not be used for a per-thread breakpoint
in any thread of the target process.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX.
These requests read per-thread breakpoint values from breakpoint regis‐
ters.
They are identical to and respectively in other
respects.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX.
These requests allow the calling process to access stacked general reg‐
ister
values that have not yet been written to the RSE backing
store. data bytes that would have been spilled at addr
on the user's RSE backing store, had the RSE been
flushed, are copied to or from addr2 in the calling
process. The addr argument must be 8-byte-aligned and
conform to ≤ addr < data must be a multiple of 8 bytes,
and addr+data must also conform to ≤ addr+data <= As a
special case, to retrieve the final NaT collection, addr
== and data == is also accepted.
Note: This facility should be used only to modify values
of registers that were dirty when the thread was
stopped. Do not use this facility if the values of
ar.bsp or ar.bspstore have been modified.
Note: These requests are not supported on PA-RISC ver‐
sions of HP-UX.
With these requests, on Itanium-based systems the register specified by
addr is returned to the calling process making the
request. The data argument is the size of the read.
The addr2 argument points to the location in the calling
process's address space where the data will be written.
The addr argument must be a value defined by __uregs_t
in
The registers that may be read or written vary depending
on whether the target thread is stopped in a syscall or
interruption context. Retrieve the __reason value first
to determine which applies. The following registers may
be read or written in each context:
───────────────────────────────────────────────────────────────────────
Reg Interruption Syscall Notes
───────────────────────────────────────────────────────────────────────
__gp R/W R/W Global Pointer
__r1
───────────────────────────────────────────────────────────────────────
__r2-__r3 R/W Reads as 0 Scratch registers
───────────────────────────────────────────────────────────────────────
__r4-__r7 R/W R/W
───────────────────────────────────────────────────────────────────────
__ret0-__ret3 R/W R/W
__r8-__r11
───────────────────────────────────────────────────────────────────────
__sp R/W R/W
__r12
───────────────────────────────────────────────────────────────────────
__tp R/W R/W
__r13
───────────────────────────────────────────────────────────────────────
__r14-__r31 R/W Reads as 0
───────────────────────────────────────────────────────────────────────
__r32-__r127 See TT_LWP_RDRSEBS and
TT_LWP_WRRSEBS
───────────────────────────────────────────────────────────────────────
__f2-__f5 R/W R/W
───────────────────────────────────────────────────────────────────────
__f6-__f15 R/W Read as 0.0
───────────────────────────────────────────────────────────────────────
__f16-__f31 R/W R/W
───────────────────────────────────────────────────────────────────────
__f32-__f127 R/W Read as 0.0 Writes may return if the
Hi FP registers were not
live when the target
thread stopped.
───────────────────────────────────────────────────────────────────────
__pr R/W R/W Writes to p6-p15 in a
syscall context may be
ignored.
───────────────────────────────────────────────────────────────────────
__p1-__p5 R/W R/W
───────────────────────────────────────────────────────────────────────
__p6-__p11 R/W R/W Writes in a syscall con‐
text may be ignored.
───────────────────────────────────────────────────────────────────────
__p12-__p63 R/W R/W
───────────────────────────────────────────────────────────────────────
__b0/__rp R/W R/W
───────────────────────────────────────────────────────────────────────
__b1-__b5 R/W R/W
───────────────────────────────────────────────────────────────────────
__b6-__b7 R/W Read as 0
───────────────────────────────────────────────────────────────────────
__um R/W R/W
───────────────────────────────────────────────────────────────────────
__ar_kr7 R R Syscall Vector table
__ar7 pointer
───────────────────────────────────────────────────────────────────────
__ar_rsc R/W R/W
__ar16
───────────────────────────────────────────────────────────────────────
__ar_bsp Value reflects effects of
__ar17 R R br.call (syscall) or
cover (interruption).
───────────────────────────────────────────────────────────────────────
__ar_bspstore R R
__ar18
───────────────────────────────────────────────────────────────────────
__ar_rnat See TT_LWP_RDRSEBS and
__ar19 TT_LWP_WRRSEBS
───────────────────────────────────────────────────────────────────────
__ar_csd R/W Reads as 0
__ar25
───────────────────────────────────────────────────────────────────────
__ar_ssd R/W Reads as 0
__ar26
───────────────────────────────────────────────────────────────────────
__ar_ccv R/W Reads as 0
__ar32
───────────────────────────────────────────────────────────────────────
__ar_unat R/W R/W
__ar36
───────────────────────────────────────────────────────────────────────
__ar_fpsr R/W R/W
__ar40
───────────────────────────────────────────────────────────────────────
__ar_pfs R/W R
__ar64
───────────────────────────────────────────────────────────────────────
__ar_lc R/W R/W
__ar65
───────────────────────────────────────────────────────────────────────
__ar_ec R/W R/W
__ar66
───────────────────────────────────────────────────────────────────────
__reason R R 0 == syscall context,
non-zero == interruption
context
───────────────────────────────────────────────────────────────────────
__ip R/W R/W Low-order 2-bits indicate
slot number.
───────────────────────────────────────────────────────────────────────
__cfm R/W R/W Current Frame Marker cor‐
responding to __ip
───────────────────────────────────────────────────────────────────────
__ed R/W Reads as 0 May not be set if not
previously set.
───────────────────────────────────────────────────────────────────────
__cr_isr R
__cr17
───────────────────────────────────────────────────────────────────────
__cr_iipa R
__cr22
───────────────────────────────────────────────────────────────────────
On PA-RISC systems, the words at offset
addr in the structure are returned to the calling
process. The data argument is the size of the read.
The addr2 argument points to the location in the calling
process's address space where the data will be written.
The addr argument must be word-aligned and addr+data
must be less than or equal to (see the file
Note: On Itanium-based systems, 8, 9 and 16 byte reads
are supported. Static general registers may be read
with 8 or 9 byte requests. The NaT bit corresponding to
the general register is returned in bit 0 of the 9th
byte if requested. Floating point register reads must
be 16 byte requests. All other register reads must be 8
byte requests. Individual bits, such as __p1...__p63,
will be returned in bit 0 of an 8 byte word.
On PA-RISC systems, only 4 and 8 byte reads and writes
are currently supported.
With this request, on Itanium-based systems:
data bytes of data pointed to by addr2 are written to
the register specified by addr which must be a __uregs_t
value as noted above. On PA-RISC systems: data bytes of
data pointed to by addr2 are written at offset addr in
the structure. Only these locations can be written in
this way: the general registers, most floating-point
registers, a few control registers, and certain bits of
the interruption processor status word.
Note: On Itanium-based systems, 8, 9 and 16 byte writes
are supported. Static general registers may be written
as 8 or 9 byte requests. Bit 0 of the 9th byte is writ‐
ten to the NaT bit corresponding to the general register
if requested. An 8 byte write to a static general reg‐
ister will clear the corresponding NaT bit. Floating
point register writes must be 16 byte requests. All
other register writes must be 8 byte requests.
On PA-RISC systems, only 4 and 8 bytes reads and writes
are currently supported. For all vectored requests
(those prefixed by pid is the process ID of the target
process.
This request performs a series of requests on arbitrary threads within
a single target process specified by pid. The lwpid
argument must be 0 (zero).
The addr argument points to an array of up to in the
calling process's address space. Each contains a
request to be performed and the corresponding arguments.
The contains at least the following fields:
─────────────────────────────────────────────────────────
Name Type Description
─────────────────────────────────────────────────────────
ttv_req ttreq_t Request (Limited to: TT_LWP_STOP,
TT_LWP_CONTINUE, TT_LWP_RUREGS,
TT_LWP_WUREGS)
─────────────────────────────────────────────────────────
ttv_lwpid lwpid_t Light-Weight Process (thread) ID
specifying a valid thread within
the target process on which to
perform request ttv_req
─────────────────────────────────────────────────────────
ttv_addr uint64_t addr argument to request ttv_req
─────────────────────────────────────────────────────────
ttv_data uint64_t data argument to request ttv_req
─────────────────────────────────────────────────────────
ttv_addr2 uint64_t addr2 argument to request ttv_req
The array of must be cleared (for example, with prior to filling in
the fields listed above. (The names of fields in this
structure, other than those listed above, (if any) are
subject to change without notice.)
See the descriptions of the individual requests for
details of the addr, data and addr2 arguments required
for each.
The data argument specifies the number of request ele‐
ments in the array pointed to by addr.
The addr2 argument points to a location in the calling
process's address space containing a single The contains
at least the following fields:
────────────────────────────────────────────
Name Type Description
────────────────────────────────────────────
ttvr_count uint64_t Points to an 8-byte
location in the
calling process's
address space into
which the count of
successful requests
will be written.
────────────────────────────────────────────
ttvr_ret1 uint64_t Points to an array
of at least data
8-byte elements in
the calling
process's address
space into which
the return values
of the individual
requests (if any)
will be written.
────────────────────────────────────────────
The must be cleared (for example, with prior to filling in
the fields listed above.
On return, ttvr_count will contain the number of
requests from the array pointed to by addr which suc‐
ceeded. stops processing requests from the array upon
encountering an error.
The first ttvr_count elements of the array pointed to by
ttvr_ret1 will be filled in with the return values of
the corresponding requests. Although none of the
requests supported by at this time produce return val‐
ues, additional requests which produce return values may
be supported in the future.
This request performs a series of
requests on a single thread within the target process in
a single call. The lwpid argument must specify a valid
thread within the target process.
The addr argument points to a location in the calling
process's address space containing an array of up to
each containing the arguments for the request(s) to be
performed. The structure contains the following fields:
───────────────────────────────────────────────────
Name Type Description
───────────────────────────────────────────────────
ttrv_reg uint64_t Register to read
───────────────────────────────────────────────────
ttrv_size uint64_t Size to read
───────────────────────────────────────────────────
ttrv_addr Points to the loca‐
tion in the calling
process's address
space where the
data will be writ‐
ten.
───────────────────────────────────────────────────
The ttrv_reg, ttrv_size, and ttrv_addr arguments correspond
to the addr, data, and addr2 arguments (respectively) of
the request. See the description of the request for
details.
The data argument specifies the number of request ele‐
ments in the array pointed to by addr.
The addr2 argument points to an 8-byte location in the
calling process's address space into which the number of
successful requests will be written. The request stops
processing requests upon encountering an error. There
is currently only one non debug-related request:
This call returns the
of the operating system and has been introduced to help
debugger developers make their tools more portable from
one version to another. The pid, lwpid, addr, data, and
addr2 arguments must be 0 (zero).
11.0 systems can be identified by the fact that this
call will return an error. Later releases will return
the value the operating system was compiled with (see
The release levels for systems newer than 11.0 are:
Level 5: internal change.
Level 6: add attach option.
Level 7: add event.
Level 8: add requests.
Level 9: add requests.
Level 10: add events.
Level 11: allow the request to generate user specified
core file names.
Level 12: add requests.
Level 13: add events.
Level 14: add requests; add syscall timestamps; and add
settrc/attach option.
Events
As noted earlier, a tracing process can set event flags in the context
of a traced process, or its individual threads, to cause the threads to
respond to specific events during their execution. When an event flag
is set in the context of the process, all threads in the process
respond to the event. When set in the context of a thread, only the
specific thread will respond to the event. If an event is requested by
the process, the event mask of the thread is not examined. For the
event mask of the thread to be significant, the process event must be
be unset. Similarly, if an event option is enabled in the process, the
option for the thread is not considered. Event masks may be inherited
across using the options in the structure. If is set, the child
process inherits the event mask of its parent. If is set, the lwp
inherits the event mask of the lwp that invoked If the latter is set,
the lwp created by also inherits the event mask of the creating thread.
These events are:
This event flag indicates that the traced thread needs to examine
signal mask bits when processing signals. This means
that, by default, threads stop when receiving a sig‐
nal. If the signal being processed has its mask bit
set, signal processing continues as though the
process were not traced: the traced thread is not
stopped, and the tracing process is not notified of
the signal. On the other hand, if the signal mask
bit is not set for the signal being processed, the
traced thread is stopped and the tracing process is
notified via
Note that the SIGKILL signal can never be unmasked.
It behaves as though its mask bit were always set.
This means that a SIGKILL signal cannot be used to
stop a traced thread. The SIGTRAP signal is also
special in that it is used to stop traced threads
when they respond to a trap, such as a breakpoint or
a single step. Consequently, masking SIGTRAP, even
though allowed, will result in unexpected behavior in
these conditions.
This event flag indicates that the traced thread needs to take special
action when it invokes When set, both the parent
thread and the initial thread in the child process
stop (after the child process is marked as a traced
process and adopts its parent's debugger). Both
threads log the fact that they stopped in response to
a event. The parent thread provides the of the child
process in the appropriate portion of the structure.
The initial thread of the child process provides the
pid of the parent in the same location. See the
structure description for further details.
This event flag indicates that the traced thread needs to take special
action when it invokes The behavior is identical to
that of but it is important to note that the caveats
with respect to continue to apply here. In particu‐
lar, it needs to be remembered that when the child
process stops, its parent is asleep, and that the
child borrows the parent's address space until a call
to or an exit (either by a call to or abnormally)
takes place. Continuing the parent process before
the above steps take place results in an error.
This event flag indicates that the traced thread needs to notify
the debugger, during a or operation, just after the
child process ID and thread ID is known and before
the child process is created and set to run. The
parent thread is stopped and it provides the pid of
the child process and lwpid of the child's initial
thread.
Note: Upon continuation from this event, the traced
thread does not guarantee that the child process with
an earlier returned pid and lwpid can be created
since the or operation might fail.
This event flag indicates that the traced thread needs to notify
the debugger upon the failure of a or operation. The
traced parent thread is stopped and returns the error
code for fork failure.
This event flag indicates that a traced thread needs to notify the
debugger
upon completion of loading the new executable file,
in the system call. The length of the pathname
string (not including a null terminating character)
is returned in the structure. The path may subse‐
quently be obtained using the request.
This event flag indicates that the traced process will notify the
debugger upon return of all system calls. The traced
process will also provide the following information:
the system call number, its number of arguments and
all its arguments, its return value and its error
return in the structure. If the system call is a or
and if, respectively, the or event is set, only the
notification associated with these events is per‐
formed. See the request.
This event flag requests notification of system call entry points. By
default, all system calls stop at this event if it is
selected. The information provided is the same as
for events but the return value and error are always
zero.
Identical to but for system call restarts.
This event flag indicates that the traced process needs to notify the
debugger action when it invokes When set, the traced
thread stops while still potentially multithreaded.
This event flag indicates that the debugger wants to be notified when
the
system call is invoked to create a thread. When set,
the calling thread stops and provides the debugger
with the lwpid of the newly created thread.
This event flag indicates that the debugger wants to be notified
when a thread is exiting via the system call. The
thread stops upon entry to the system call.
This event flag indicates that the debugger wants to be notified
when a caller thread invokes the call on a target
thread. When set, the calling thread stops upon
entering the system call and provides the lwpid of
the thread to be terminated in the structure.
This event flag indicates that the debugger is to be notified when the
system call is invoked. The lwpid of the target
thread is provided in the structure.
This event flag tells the kernel to perform event-based single-stepping
and breakpoint notification. If this event is
requested, SIGTRAP loses all special meaning. It is
highly recommended that debuggers use this event
instead of the old signal-based method as it will
allow breakpoints and single-steps to take place
regardless of the signals the thread is blocking.
Unlike the signal-based method, it also guarantees
that single-steps and breakpoint events are generated
in the context of the thread even if other threads
are active in the process.
Note that mixing signal-based and event-based break‐
point/single-stepping may result in unexpected SIG‐
TRAPs being posted to the process being debugged.
Security Restrictions
For security reasons, inhibits the set-user-ID facility on subsequent
calls.
Some or all of the actions associated with this system call require the
privilege. Processes owned by the superuser have this privilege. Pro‐
cesses owned by other users may have this privilege, depending on sys‐
tem configuration. See privileges(5) for more information about privi‐
leged access on systems that support fine-grained privileges.
ERRORS
If a request fails, returns and is set to one of the following:
The pid argument to the or is the pid of the invoker.
The process identified by the
pid argument to or is exiting.
The process is already being traced.
Unable to attach to a process. This error can only be encoun‐
tered when
attaching to a process in the middle of an
syscall.
One thread of a multithreaded process (p1) has performed a
the child (p2) is stopped at the vfork event and
the debugger is attempting to stop or resume a
thread in the parent process (p1).
Invalid user address.
Cannot suspend process or attach is interrupted
request is an illegal number.
A non-zero value has been passed in a parameter expecting a zero
value or
vice-versa.
The data argument of or or is not
Size too large for data transfer.
Invalid signal number.
Misaligned request or not a word multiple
Invalid signal
Invalid offset
An offset in the
structure is not word-aligned.
An invalid register is targeted by
The core file argument to a
request exists and is not a regular file.
The data argument to is greater than
An invalid request is specified in the
field of a passed to
Undocumented fields in a
passed to are not 0 (zero).
The or field of a passed to is NULL.
The size argument to a
is larger than
Data in this register is not readable or not writable at this
time.
The directory portion of the core file argument to a
request does not exist.
System is out of memory.
Attempting to stop a thread already stopped by the debugger.
Attempting to resume a thread not stopped by the debugger.
Attempting to read or write registers while the thread is not
stopped.
Attempting to obtain the state of a thread which was not stopped
by the debugger.
Invoked before an exec event took place
The process is exiting and the request is not allowed in this
condition.
The debugger is attempting to modify wide registers after having
modified narrow registers.
The debugger is attempting to first modify the text of a process
in
the middle of a vfork. Text modification is
allowed during vfork as long as it was first mod‐
ified before the vfork.
pid and/or lwpid identify a process or a thread to be
traced that does not exist or has not executed a
with the request.
EXAMPLES
A simple no-frills system call tracer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/ttrace.h>
#include <sys/scall_define.h>
pid_t ppid;
typedef struct {
int val;
char *name;
} _exp_t;
static char *
gen_name(_exp_t *base, int val)
{
_exp_t *rp;
for (rp = base; rp->name; rp++) {
if (val == rp->val) {
return rp->name;
}
}
return NULL;
}
static char *
ev_name(ttevents_t ev)
{
static char buf[32];
char *p;
static _exp_t tab[] = {
TTEVT_SIGNAL, "SIGNAL",
TTEVT_FORK, "FORK",
TTEVT_EXEC, "EXEC",
TTEVT_EXIT, "EXIT",
TTEVT_VFORK, "VFORK",
TTEVT_SYSCALL, "SYSCALL",
TTEVT_SYSCALL_ENTRY, "SYSCALL_ENTRY",
TTEVT_LWP_CREATE, "LWP_CREATE",
TTEVT_LWP_TERMINATE, "LWP_TERMINATE",
TTEVT_LWP_EXIT, "LWP_EXIT",
TTEVT_LWP_ABORT_SYSCALL,"LWP_ABORT_SYSCALL",
#if TT_FEATURE_LEVEL >= 7
TTEVT_BPT_SSTEP, "LWP_BPT_SSTEP",
#endif
-1, NULL
};
p = gen_name(tab, (int) ev);
if (p) {
return p;
}
(void) sprintf(buf, "EVENT_%#x", ev);
return buf;
}
static void
errexit(const char *p)
{
(void) fprintf(stderr, "%s: %s\n", p, strerror(errno));
if (ppid) {
(void) kill(ppid, SIGINT);
}
exit (1);
}
static void
dottrace(ttreq_t req, pid_t pid, lwpid_t lwpid, uint64_t addr, uint64_t data,
uint64_t addr2)
{
int rval;
char *p;
static _exp_t tab[] = {
TT_PROC_SETTRC, "PROC_SETTRC",
TT_PROC_ATTACH, "PROC_ATTACH",
TT_PROC_ATTACH_NOSTOP, "PROC_ATTACH_NOSTOP",
TT_PROC_DETACH, "PROC_DETACH",
TT_PROC_CONTINUE, "PROC_CONTINUE",
TT_PROC_SET_EVENT_MASK, "PROC_SET_EVENT_MASK",
TT_PROC_GET_FIRST_LWP_STATE, "PROC_GET_FIRST_LWP_STATE",
TT_PROC_GET_NEXT_LWP_STATE, "PROC_GET_NEXT_LWP_STATE",
TT_LWP_CONTINUE, "LWP_CONTINUE",
-1, NULL
};
rval = ttrace(req, pid, lwpid, addr, data, addr2);
if (rval == -1) {
p = gen_name(tab, req);
errexit(p ? p : "ttrace");
}
}
static void
show_syscall(const ttstate_t *stp)
{
int nargs = stp->tts_scnargs;
ttevents_t evt = stp->tts_event;
int i;
char *p;
const uint64_t *argp;
static _exp_t tab[] = {
SYS_open, "open",
SYS_close, "close",
SYS_read, "read",
SYS_write, "write",
SYS_ioctl, "ioctl",
SYS_lseek, "lseek",
SYS_fstat, "fstat",
SYS_stat, "stat",
SYS_poll, "poll",
SYS_select, "select",
SYS_mmap, "mmap",
SYS_wait, "wait",
SYS_waitpid, "waitpid",
SYS_waitid, "waitid",
SYS_time, "time",
SYS_brk, "brk",
SYS_sigsuspend, "sigsuspend",
SYS_sigprocmask, "sigprocmask",
SYS_sigtimedwait, "sigtimedwait",
-1, NULL,
};
if (stp->tts_scno == SYS_siginhibit || stp->tts_scno == SYS_sigenable) {
return;
}
if (evt == TTEVT_NONE) {
evt = TTEVT_SYSCALL;
}
p = gen_name(tab, stp->tts_scno);
if (p == NULL) {
char buf[32];
(void) sprintf(buf, "syscall_%#x", stp->tts_scno);
p = buf;
}
(void) printf("%s", p);
for (i = 0; i < nargs; i++) {
(void) printf("(");
for (i = 0, argp = stp->tts_scarg; i < nargs; i++, argp++) {
(void) printf("%#llx", *argp);
(void) printf("%s",
(i == nargs - 1) ? "" : ", ");
}
(void) printf(")");
}
if (stp->tts_event == TTEVT_SYSCALL_RETURN) {
if (stp->tts_u.tts_syscall.tts_errno) {
(void) printf(" ERR%d",
stp->tts_u.tts_syscall.tts_errno);
}
else {
(void) printf(" = %lld",
stp->tts_u.tts_syscall.tts_rval[0]);
}
}
else {
(void) printf(" ...");
}
(void) printf("\n");
}
static void
show_event(const ttstate_t *stp)
{
switch(stp->tts_event) {
case TTEVT_NONE:
case TTEVT_SYSCALL:
case TTEVT_SYSCALL_ENTRY:
case TTEVT_SYSCALL_RESTART:
show_syscall(stp);
break;
case TTEVT_EXIT:
(void) printf("%s %d\n", ev_name(stp->tts_event),
stp->tts_u.tts_exit.tts_exitcode);
break;
case TTEVT_SIGNAL:
(void) printf("%s %d\n", ev_name(stp->tts_event),
stp->tts_u.tts_signal.tts_signo);
break;
default:
(void) printf("%s\n", ev_name(stp->tts_event));
}
}
main(int argc, char **argv)
{
ttevent_t ev;
ttstate_t st;
pid_t pid;
int pfd1[2];
int pfd2[2];
char c;
--argc, ++argv;
pid = atoi(*argv);
ev.tte_events = TTEVT_SYSCALL|TTEVT_EXEC|TTEVT_EXIT;
ev.tte_opts = TTEO_NONE;
if (pid) {
siginfo_t si;
dottrace(TT_PROC_ATTACH, pid, 0, TT_DETACH_ON_EXIT,
TT_VERSION, 0);
if (waitid(P_PID, pid, &si, WEXITED|WSTOPPED) < 0 ||
si.si_pid != pid || si.si_code != CLD_STOPPED) {
errexit("waitid");
}
dottrace(TT_PROC_GET_FIRST_LWP_STATE, pid, 0, (uint64_t) &st,
(uint64_t) sizeof st, 0);
show_event(&st);
dottrace(TT_PROC_SET_EVENT_MASK, pid, 0,
(uint64_t) &ev, sizeof ev, 0);
}
else {
if (pipe(pfd1) < 0 || pipe(pfd2) < 0) {
errexit("pipe");
}
switch(pid = fork()) {
case -1:
errexit("fork");
case 0:
ppid = getppid();
dottrace(TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0);
/* tell parent we are SETTRC'ed */
if (write(pfd2[1], (void *) &c, sizeof c) != sizeof c) {
errexit("write");
}
/* wait for exec event to be set*/
if (read(pfd1[0], (void *) &c, sizeof c) != sizeof c) {
errexit("read");
}
(void) close(pfd1[0]);
(void) close(pfd1[1]);
(void) close(pfd2[0]);
(void) close(pfd2[1]);
(void) execvp(*argv, argv);
ppid = 0;
errexit("exec");
}
if (read(pfd2[0], (void *) &c, sizeof c) != sizeof c) {
errexit("read");
}
dottrace(TT_PROC_SET_EVENT_MASK, pid, 0,
(uint64_t) &ev, sizeof ev, 0);
/* tell the child to exec */
if (write(pfd1[1], (void *) &c, sizeof c) != sizeof c) {
errexit("write");
}
(void) close(pfd1[0]);
(void) close(pfd1[1]);
(void) close(pfd2[0]);
(void) close(pfd2[1]);
}
dottrace(TT_PROC_CONTINUE, pid, 0, 0, 0, 0);
for (;;) {
int rval = ttrace_wait(pid, 0, TTRACE_WAITOK, &st, sizeof st);
if (rval < 0) {
errexit("ttrace_wait");
}
show_event(&st);
if (st.tts_event == TTEVT_EXIT) {
break;
}
dottrace(TT_LWP_CONTINUE, pid, st.tts_lwpid, TT_NOPC,
st.tts_event == TTEVT_SIGNAL ?
(uint64_t) st.tts_u.tts_signal.tts_signo : 0L, 0L);
}
return 0;
}
WARNINGS
If the addr argument to a or request is not the Instruction Address
Offset Queue (program counter) is loaded with the values addr and
addr+4 before execution resumes. Otherwise, execution resumes from the
point where it was interrupted.
AUTHOR
was developed by HP.
SEE ALSOadb(1), coreadm(1M), coreadm(2), exec(2), fork(2), signal(2),
ttrace_wait(2), vfork(2), wait(2), privileges(5).
STANDARDS CONFORMANCEttrace(2)