Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
HP-UX Reference > T

ttrace(2)

HP-UX 11i Version 3: February 2007
» 

Technical documentation

» Feedback
Content starts here

 » Table of Contents

 » Index

NAME

ttrace() — tracing facility for multithreaded processes

SYNOPSIS

#include <sys/ttrace.h> int ttrace (ttreq_t request, pid_t pid, lwpid_t lwpid, uint64_t addr, uint64_t data, uint64_t addr2);

Remarks

While the POSIX API is defined and will not change, the present underlying system calls are not guaranteed to be compatible with future versions.

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 ttrace() system call provides a means by which a process can control the execution of another process. Its primary use is for the implementation of breakpoint and event driven debugging; see adb(1) and dde(1). ttrace() is designed to function for both single and multithreaded traced processes. 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 EVENTS section below) at which time the thread enters a stopped state and the tracing process is notified via ttrace_wait().

Requests

Most of the ttrace() requests are to be used only by the tracing process. However, some requests (those suffixed by _NOATTACH) can be used by any process provided 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 OWNER privilege.

ttrace() 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 ttrace() and is one of the following:

Process-Wide Requests

For all process-wide requests (those prefixed by TT_PROC_), pid is the process ID of the target process and lwpid must be set to zero.

TT_PROC_SETTRC

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 exec(). If the value is TT_GEN_SHLIB_BPT, 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 TT_VERSION. Peculiar results occur if the parent does not expect to trace the child.

Note: It is critical for future backward compatibility that the TT_VERSION macro itself be used and not its value.

TT_PROC_ATTACH

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 calling process must match the real and saved uid of the process pid unless the tracing process has the OWNER privilege.

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 TT_KILL_ON_EXIT, the attached process(es) will be killed. If the value is TT_DETACH_ON_EXIT, the attached process(es) will be resumed and detached as if the debugger had performed a TT_PROC_DETACH request.

The addr2 argument specifies the action to be taken by the loader when the target process does an exec(). If the value is TT_GEN_SHLIB_BPT, 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 TT_VERSION (see TT_PROC_SETTRC above).

TT_PROC_DETACH

This request detaches the traced process and allows it to continue executing. It behaves identically to TT_PROC_CONTINUE except that the process is no longer being traced after the call returns.

For this request, the lwpid, addr, data, and addr2 arguments must be set to zero.

TT_PROC_RDTEXT, TT_PROC_RDTEXT_NOATTACH

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.

TT_PROC_RDDATA, TT_PROC_RDDATA_NOATTACH

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.

TT_PROC_WRTEXT, TT_PROC_WRDATA

These requests allow writing into the target process text (TT_PROC_WRTEXT) and data spaces (TT_PROC_WRDATA).

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.

TT_PROC_STOP

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.

TT_PROC_CONTINUE

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.

TT_PROC_GET_PATHNAME

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 exec(). 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 ttstate_t structure returned via the TT_LWP_GET_STATE or other ttrace 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.

TT_PROC_GET_EVENT_MASK

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 ttevent_t data structure in user space pointed to by addr.

The lwpid and addr2 arguments must be set to zero.

The ttevent_t data structure is as follows:

typedef struct { sigset_t tte_signals; ttevents_t tte_events; tteopt_t tte_opts;

} ttevent_t;

The options provided in tte_opts control the behavior of child processes produced by fork() and are as follows:

TTEO_NONE = 0x0000 TTEO_NOSTRCCHLD = 0x0001 TTEO_PROC_INHERIT = 0x0002 TTEO_LWP_INHERIT = 0x0004 TTEO_NORM_SIGTRAP = 0x0008

If TTEO_NOSTRCCHLD is set, the child process resulting from a fork() will not be traced. This makes it possible for a debugger to debug another debugger. The TTEO_PROC_INHERIT and TTEO_LWP_INHERIT options allow events to be inherited by child processes and threads respectively. Refer to the EVENTS section below.

If TTEO_NORM_SIGTRAP is set, the SIGTRAP signal behaves normally. That is, it is getting delivered (the default behavior is to drop these signals).

TT_PROC_SET_EVENT_MASK

This request allows the tracing process to establish events and signals the traced process will respond to. Refer to the EVENTS section for a description of these events.

The addr argument is a pointer to a ttevent_t structure to be copied into the target process. The data argument specifies the number of bytes to be transferred.

The lwpid and addr2 arguments must be set to zero.

TT_PROC_GET_SIGMASK

This request returns the process-wide signal mask value for the target process that was set using TT_PROC_SET_SIGMASK.

The data argument specifies the number of bytes to be read from the context of the traced process into the ttmask_t data structure in user space pointed by addr.

The lwpid and addr2 arguments must be set to zero.

The ttmask_t data structure is as follows:

typedef struct { sigset_t ttm_signals; ttmopt_t ttm_opts;

} ttmask_t;

The options provided in ttm_opts control the behavior of signal masks on child processes produced by fork() and are as follows:

TTMO_NONE = 0x0000 TTMO_PROC_INHERIT = 0x0001 TTMO_LWP_INHERIT = 0x0002

The TTMO_PROC_INHERIT and TT_LWP_INHERIT option allow signal masks to be inherited by child processes and threads respectively.

TT_PROC_SET_SIGMASK

This request allows the tracing process to change the signal mask on the target process.

The addr argument is a pointer to a ttmask_t structure to be copied into the target process. The data argument specifies 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 ttm_signals field in the ttmask_t structure. Setting the ttm_signals to an empty set results in clearing the signal mask that was previously set using this request.

TT_PROC_GET_FIRST_LWP_STATE

This request returns the ttstate_t structure associated with the first thread on the stopped list. It resets the list pointer to the first entry in the list. The TT_PROC_GET_NEXT_LWP_STATE 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 ttstate_t data structure in the user space pointed to by addr. The lwpid and addr2 arguments must be zero.

The ttstate_t 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 TTS_WAITEDFOR bit, is invariant until the thread is resumed. Its layout is as follows:

typedef struct { pid_t tts_pid; lwpid_t tts_lwpid; uint64_t tts_user_tid; ttevents_t tts_event; ttsf_t tts_flags; int tts_scno; int tts_scnargs; uint64_t tts_scarg[SCALL_MAXARGS]; union {

ttexec_data_t tts_exec; ttfork_data_t tts_fork; ttprefork_data_t tts_prefork; ttsignal_data_t tts_signal; ttthread_data_t tts_thread; ttsyscall_data_t tts_syscall; ttexit_data_t tts_exit; ttbpt_data_t tts_bpt_sstep; char tts_fill[128];

} tts_u;

} ttstate_t;

tts_pid is the process ID.

tts_lwpid is the lwpid of the stopped thread.

tts_user_tid is the thread's user ID.

tts_event is the event that caused the stop (TTEVT_NONE if the thread stopped because of a ttrace command).

The tts_flags 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 ttrace_wait(), 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 exit() system call. The values are as follows:

TTS_WASSUSPENDED = 0x0001 TTS_WASSLEEPING = 0x0002 TTS_WASRUNNING = 0x0004 TTS_WAITEDFOR = 0x0008 TTS_INSYSCALL = 0x0010 TTS_IS32BIT = 0x0020 TTS_ATEXIT = 0x0040

The following three arguments provide information regarding the system call being executed when the thread was stopped. This information is valid only if the TTS_INSYSCALL bit is set in tts_flags.

tts_scno is the system call number.

tts_scnargs is the number of arguments of the system call.

tts_scarg is the argument list of the system call.

The data associated with a TTEVT_EXEC event is as follows:

typedef struct { int tts_pathlen;

} ttexec_data_t;

tts_pathlen is the length of the pathname of the exec() system call.

The data associated with a TTEVT_FORK, TTEVT_VFORK or TTEVT_FORK_FAIL event is as follows:

typedef struct { pid_t tts_fpid; lwpid_t tts_flwpid; int tts_isparent; int tts_errno;

} ttfork_data_t;

tts_fpid is the process ID of the other side of the fork. This field is set to zero for the TTEVT_FORK_FAIL event.

tts_flwpid is the thread ID of the other side of the fork. This field is set to zero for the TTEVT_FORK_FAIL event.

tts_isparent is zero for the child event and one for the parent.

tts_errno is set to error code indicating the reason for error in TTEVT_FORK_FAIL event. This field is set to zero for the TTEVT_FORK and TTEVT_VFORK events.

The data associated with a TTEVT_PREFORK event is as follows:

typedef enum { TTS_FORK, TTS_VFORK

} ttpf_t;

typedef struct { pid_t tts_fpid; lwpid_t tts_flwpid; ttpf_t tts_type;

} ttprefork_data_t;

tts_fpid is the process ID of the other side of the fork.

tts_flwpid is the thread ID of the other side of the fork.

tts_type is the type of fork.

The data associated with a TTEVT_SIGNAL event is as follows:

typedef struct { int tts_signo; ttsigf_t tts_sigflags; uint64_t tts_sigaction; siginfo_t tts_siginfo;

} ttsignal_data_t;

tts_signal is the signal number.

tts_sigflags is TTSF_USERSIGINFO if a siginfo was delivered with the signal, 0 otherwise.

tts_sigaction is the disposition of the signal.

tts_siginfo is the siginfo, if applicable.

The data associated with a TTEVT_LWP_CREATE, TTEVT_LWP_TERMINATE or TTEVT_LWP_ABORT_SYSCALL event is as follows:

typedef struct { lwpid_t tts_target_lwpid;

} ttthread_data_t;

tts_target_lwpid is the lwpid of the targeted lwp.

The data associated with a TTEVT_SYSCALL event is as follows:

typedef struct { int64_t tts_rval[2]; int tts_errno;

} ttsyscall_data_t;

The tts_rval fields are the return value(s) of the system call.

tts_errno is the error status if the system call failed.

The data associated with a TTEVT_LWP_EXIT event is as follows:

typedef struct { int tts_exitcode;

} ttexit_data_t;

tts_exitcode is the exit code of the process.

The data associated with a TTEVT_BPT_SSTEP event is as follows:

On PA-RISC systems:

typedef struct { int tts_isbpt;

} ttbpt_data_t;

tts_isbpt 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 Itanium(\rg-based systems:

typedef enum { TTBPT_SSTEP = 0, /* Single stepping */ TTBPT_BPT, /* Breakpoint */ TTBPT_TBRANCH /* Taken Branch */

} ttbpt_type_t;

typedef struct { ttbpt_type_t tts_isbpt;

} ttbpt_data_t;

TT_PROC_GET_NEXT_LWP_STATE

This request is identical to TT_PROC_GET_FIRST_LWP_STATE 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.

TT_PROC_GET_MPROTECT

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 specifies 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.

TT_PROC_SET_MPROTECT

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 modified. 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.

TT_PROC_SET_SCBM

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 TTSCBM_SELECT or TTSCBM_UNSELECT 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.

TT_PROC_EXIT

This request causes the traced process to terminate. It has the same consequence as exit() being invoked by one of the process threads. The lwpid, addr, data, and addr2 arguments must be zero.

TT_PROC_CORE

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 MAXPATHLEN 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 coreadm() and coreadm: 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 core.pid.

TT_PROC_GET_NUM_IBPT_REGS, TT_PROC_GET_NUM_DBPT_REGS

These requests return the number of physical hardware instruction or data breakpoint registers that are available for use.

TT_PROC_SET_IBPT_REGS, TT_PROC_SET_DBPT_REGS

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 Itanium-based systems, addr must be an even number less than the value returned by TT_PROC_GET_NUM_IBPT_REGS or TT_PROC_GET_NUM_DBPT_REGS 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 breakpoints. 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 break instructions that may be present in the program text.

Note: These requests are not supported on PA-RISC versions of HP-UX.

TT_PROC_GET_IBPT_REGS, TT_PROC_GET_DBPT_REGS

These requests read process-wide breakpoint values from breakpoint registers. 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 versions of HP-UX.

TT_PROC_GET_ARGS, TT_PROC_GET_ARGS_NOATTACH

These requests return a pointer to the argument list passed to the initial thread of the process at execve() 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 versions of HP-UX.

Thread Requests

For all thread requests (those prefixed by TT_LWP_), pid is the process id of the target process and lwpid is the target thread within the target process.

TT_LWP_STOP

This request causes the thread identified by lwpid to stop executing. If the thread is already stopped by the debugger, or by an event, an error is returned.

The addr, data, and addr2 arguments must be zero.

TT_LWP_CONTINUE

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 by the debugger. If the thread had not previously been stopped by the debugger, an error is returned.

If addr is not TT_NOPC, that value is loaded in the program counter before execution is resumed. Unexpected behavior 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.

TT_LWP_SINGLE

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 TT_LWP_CONTINUE request.

TT_LWP_TBRANCH

This request causes the stopped thread identified by lwpid to resume execution until a taken branch instruction 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 TT_LWP_CONTINUE request.

Note: This request is not supported on PA-RISC versions of HP-UX.

TT_LWP_GET_EVENT_MASK

This request is the same as TT_PROC_GET_EVENT_MASK except for the thread identified by lwpid.

TT_LWP_SET_EVENT_MASK

This request is the same as TT_PROC_SET_EVENT_MASK except for the thread identified by lwpid.

TT_LWP_GET_SIGMASK

This request is the same as TT_PROC_GET_SIGMASK except for the thread identified by lwpid.

TT_LWP_SET_SIGMASK

This request is the same as TT_PROC_SET_SIGMASK except for the thread identified by lwpid.

TT_LWP_GET_STATE

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.

TT_LWP_SET_IBPT_REGS, TT_LWP_SET_DBPT_REGS

These requests write per-thread breakpoint values into breakpoint registers. data bytes from addr2 will be written to the instruction or data breakpoint register(s) named by addr. For Itanium-based systems, addr must be an even number less than the value returned by TT_PROC_GET_NUM_IBPT_REGS or TT_PROC_GET_NUM_DBPT_REGS 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 TT_PROC_SET_IBPT_REGS and TT_PROC_SET_DBPT_REGS respectively in other respects.

Note: The available breakpoint registers must be shared between process-wide breakpoints and per-thread breakpoints. 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 versions of HP-UX.

TT_LWP_GET_IBPT_REGS, TT_LWP_GET_DBPT_REGS

These requests read per-thread breakpoint values from breakpoint registers. They are identical to TT_PROC_GET_IBPT_REGS and TT_PROC_GET_DBPT_REGS respectively in other respects.

Note: These requests are not supported on PA-RISC versions of HP-UX.

TT_LWP_RDRSEBS, TT_LWP_WRRSEBS, TT_LWP_RDRSEBS_NOATTACH

These requests allow the calling process to access stacked general register 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 ar.bspstoreaddr < ar.bsp. data must be a multiple of 8 bytes, and addr+data must also conform to ar.bspstoreaddr+data < ar.bsp. As a special case, to retrieve the final NaT collection, addr == ar.bsp | 0x1f8 and data == 8 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 versions of HP-UX.

TT_LWP_RUREGS, TT_LWP_RUREGS_NOATTACH

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 <machine/sys/uregs.h>.

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:

RegInterruptionSyscallNotes
__gpR/WR/WGlobal Pointer
__r1   
__r2-__r3R/WReads as 0Scratch registers
__r4-__r7R/WR/W 
__ret0-__ret3R/WR/W 
__r8-__r11   
__spR/WR/W 
__r12   
__tpR/WR/W 
__r13   
__r14-__r31R/WReads as 0 
__r32-__r127  See TT_LWP_RDRSEBS and TT_LWP_WRRSEBS
__f2-__f5R/WR/W 
__f6-__f15R/WRead as 0.0 
__f16-__f31R/WR/W 
__f32-__f127R/WRead as 0.0Writes may return EINVAL if the Hi FP registers were not live when the target thread stopped.
__prR/WR/WWrites to p6-p15 in a syscall context may be ignored.
__p1-__p5R/WR/W 
__p6-__p11R/WR/WWrites in a syscall context may be ignored.
__p12-__p63R/WR/W 
__b0/__rpR/WR/W 
__b1-__b5R/WR/W 
__b6-__b7R/WRead as 0 
__umR/WR/W 
__ar_kr7RRSyscall Vector table pointer
__ar7   
__ar_rscR/WR/W 
__ar16   
__ar_bspRRValue reflects effects of br.call (syscall) or cover (interruption).
__ar17   
__ar_bspstoreRR 
__ar18   
__ar_rnat  See TT_LWP_RDRSEBS and TT_LWP_WRRSEBS
__ar19   
__ar_csdR/WReads as 0 
__ar25   
__ar_ssdR/WReads as 0 
__ar26   
__ar_ccvR/WReads as 0 
__ar32   
__ar_unatR/WR/W 
__ar36   
__ar_fpsrR/WR/W 
__ar40   
__ar_pfsR/WR 
__ar64   
__ar_lcR/WR/W 
__ar65   
__ar_ecR/WR/W 
__ar66   
__reasonRR0 == syscall context, non-zero == interruption context
__ipR/WR/WLow-order 2-bits indicate slot number.
__cfmR/WR/WCurrent Frame Marker corresponding to __ip
__edR/WReads as 0May not be set if not previously set.
__cr_isrR  
__cr17   
__cr_iipaR  
__cr22   

On PA-RISC systems, the words at offset addr in the save_state 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 sizeof (save_state_t) (see the file <machine/save_state.h>).

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.

TT_LWP_WUREGS

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 save_state 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 written to the NaT bit corresponding to the general register if requested. An 8 byte write to a static general register 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.

Vectored Requests

For all vectored requests (those prefixed by TT_VEC_), pid is the process ID of the target process.

TT_VEC_GENERIC

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 TT_VEC_MAX tt_vec_ts, in the calling process's address space. Each contains a request to be performed and the corresponding arguments. The tt_vec_t contains at least the following fields:

NameTypeDescription
ttv_reqttreq_tRequest (Limited to: TT_LWP_STOP, TT_LWP_CONTINUE, TT_LWP_RUREGS, TT_LWP_WUREGS)
ttv_lwpidlwpid_tLight-Weight Process (thread) ID specifying a valid thread within the target process on which to perform request ttv_req
ttv_addruint64_taddr argument to request ttv_req
ttv_datauint64_tdata argument to request ttv_req
ttv_addr2uint64_taddr2 argument to request ttv_req

The array of tt_vec_ts must be cleared (for example, with bzero()) 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 elements in the array pointed to by addr.

The addr2 argument points to a location in the calling process's address space containing a single tt_vec_res_t. The tt_vec_res_t contains at least the following fields:

NameTypeDescription
ttvr_countuint64_tPoints to an 8-byte location in the calling process's address space into which the count of successful requests will be written.
ttvr_ret1uint64_tPoints 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 tt_vec_res_t must be cleared (for example, with bzero()) 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 succeeded. TT_VEC_GENERIC 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 TT_VEC_GENERIC at this time produce return values, additional requests which produce return values may be supported in the future.

TT_VEC_LWP_RUREGS

This request performs a series of TT_LWP_RUREGS 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 TT_VEC_MAX tt_reg_vecs, each containing the arguments for the request(s) to be performed. The tt_reg_vec_t structure contains the following fields:

NameTypeDescription
ttrv_reguint64_tRegister to read
ttrv_sizeuint64_tSize to read
ttrv_addrPoints to the location in the calling process's address space where the data will be written. 

The ttrv_reg, ttrv_size, and ttrv_addr arguments correspond to the addr, data, and addr2 arguments (respectively) of the TT_LWP_RUREGS request. See the description of the TT_LWP_RUREGS request for details.

The data argument specifies the number of request elements 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 TT_VEC_LWP_RUREGS request stops processing requests upon encountering an error.

Non-debug-related Request

There is currently only one non debug-related request:

TT_NDR_GET_FLEV

This call returns the feature level 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 TT_FEATURE_LEVEL value the operating system was compiled with (see ttrace.h). The release levels for systems newer than 11.0 are:

Level 5:

internal change.

Level 6:

add DETACH_ON_EXIT attach option.

Level 7:

add TTEVT_BPT_SSTEP event.

Level 8:

add TT_PROC_SET_IBPT, TT_PROC_SET_DBPT, TT_PROC_GET_IBPT, TT_PROC_GET_DBPT, TT_PROC_GET_NUM_IBPT_REGS, TT_PROC_GET_NUM_DBPT_REGS, TT_PROC_GET_ARGS, TT_LWP_SET_IBPT, TT_LWP_SET_DBPT, TT_LWP_GET_IBPT, TT_LWP_GET_DBPT, TT_LWP_RDRSEBS, TT_LWP_WRRSEBS, TT_LWP_TBRANCH requests.

Level 9:

add TT_PROC_GET_SIGMASK, TT_PROC_SET_SIGMASK, TT_LWP_GET_SIGMASK, TT_LWP_SET_SIGMASK requests.

Level 10:

add TTEVT_PREFORK, TTEVT_FORK_FAIL events.

Level 11:

allow the TT_PROC_CORE request to generate user specified core file names.

Level 12:

add _NOATTACH requests.

Level 13:

add TTEVT_UT_CREATE, TTEVT_UT_EXIT events.

Level 14:

add TT_PROC_GET_ARGS_NOATTACH, TT_VEC_GENERIC, TT_VEC_LWP_RUREGS requests; add syscall timestamps; and add TT_GEN_SHLIB_BPT 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.

Important

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 fork() using the tte_opts options in the ttevent_t structure. If TTEO_PROC_INHERIT is set, the child process inherits the event mask of its parent. If TTEO_LWP_INHERIT is set, the lwp inherits the event mask of the lwp that invoked fork(). If the latter is set, the lwp created by lwp_create() also inherits the event mask of the creating thread.

These events are:

TTEVT_SIGNAL

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 signal. 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 ttrace_wait().

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.

TTEVT_FORK

This event flag indicates that the traced thread needs to take special action when it invokes fork(). 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 TTEVT_FORK event. The parent thread provides the pid of the child process in the appropriate portion of the ttstate_t structure. The initial thread of the child process provides the pid of the parent in the same location. See the ttstate_t structure description for further details.

TTEVT_VFORK

This event flag indicates that the traced thread needs to take special action when it invokes vfork(). The behavior is identical to that of TTEVT_FORK but it is important to note that the caveats with respect to vfork(), continue to apply here. In particular, 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 exec() or an exit (either by a call to exit() or abnormally) takes place. Continuing the parent process before the above steps take place results in an error.

TTEVT_PREFORK

This event flag indicates that the traced thread needs to notify the debugger, during a fork() or vfork() 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 fork() or vfork() operation might fail.

TTEVT_FORK_FAIL

This event flag indicates that the traced thread needs to notify the debugger upon the failure of a fork() or vfork() operation. The traced parent thread is stopped and returns the error code for fork failure.

TTEVT_EXEC

This event flag indicates that a traced thread needs to notify the debugger upon completion of loading the new executable file, in the exec() system call. The length of the pathname string (not including a null terminating character) is returned in the ttstate_t structure. The path may subsequently be obtained using the TT_PROC_GET_PATHNAME request.

TTEVT_SYSCALL_RETURN

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 ttstate_t structure. If the system call is a fork(), vfork() or exec() and if, respectively, the TTEVT_FORK, TTEVT_VFORK or TTEVT_EXEC event is set, only the notification associated with these events is performed. See the TT_PROC_SET_SCBM request.

TTEVT_SYSCALL_ENTRY

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 TTEVT_SYSCALL_RETURN events but the return value and error are always zero.

TTEVT_SYSCALL_RESTART

Identical to TTEVT_SYSCALL_ENTRY but for system call restarts.

TTEVT_EXIT

This event flag indicates that the traced process needs to notify the debugger action when it invokes exit(). When set, the traced thread stops while still potentially multithreaded.

TTEVT_LWP_CREATE

This event flag indicates that the debugger wants to be notified when the lwp_create() 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.

TTEVT_LWP_EXIT

This event flag indicates that the debugger wants to be notified when a thread is exiting via the lwp_exit() system call. The thread stops upon entry to the system call.

TTEVT_LWP_TERMINATE

This event flag indicates that the debugger wants to be notified when a caller thread invokes the lwp_terminate() 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 ttstate_t structure.

TTEVT_LWP_ABORT_SYSCALL

This event flag indicates that the debugger is to be notified when the lwp_abort_syscall() system call is invoked. The lwpid of the target thread is provided in the ttstate_t structure.

TTEVT_BPT_SSTEP

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 breakpoint/single-stepping may result in unexpected SIGTRAPs being posted to the process being debugged.

Security Restrictions

For security reasons, ttrace() inhibits the set-user-ID facility on subsequent exec() calls.

Some or all of the actions associated with this system call require the OWNER privilege. Processes owned by the superuser have this privilege. Processes owned by other users may have this privilege, depending on system configuration. See privileges(5) for more information about privileged access on systems that support fine-grained privileges.

ERRORS

If a request fails, ttrace returns -1 and errno is set to one of the following:

EACCES

The pid argument to the TT_PROC_ATTACH is the pid of the invoker.

EACCES

The process identified by the pid argument to TT_PROC_ATTACH is exiting.

EACCES

The process is already being traced.

EAGAIN

Unable to attach to a process. This error can only be encountered when attaching to a process in the middle of an exec() syscall.

EDEADLK

One thread of a multithreaded process (p1) has performed a vfork(), 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).

EFAULT

Invalid user address.

EINTR

Cannot suspend process or attach is interrupted (TT_PROC_ATTACH).

EINVAL

request is an illegal number.

EINVAL

A non-zero value has been passed in a parameter expecting a zero value or vice-versa.

EINVAL

The data argument of TT_PROC_SETTRC or TT_PROC_ATTACH is not TT_VERSION.

EINVAL

Size too large for data transfer.

EINVAL

Invalid signal number.

EINVAL

Misaligned request or not a word multiple (TT_PROC_RDTEXT, TT_PROC_RDTEXT_NOATTACH, TT_PROC_WRTEXT).

EINVAL

Invalid signal (TT_LWP_CONTINUE, TT_LWP_SINGLE).

EINVAL

Invalid offset (TT_LWP_RUREGS, TT_LWP_RUREGS_NOATTACH, TT_LWP_WUREGS).

EINVAL

An offset in the save_state structure is not word-aligned.

EINVAL

An invalid register is targeted by TT_LWP_WUREGS.

EINVAL

The core file argument to a TT_PROC_CORE request exists and is not a regular file.

EINVAL

The data argument to TT_VEC_GENERIC is greater than TT_VEC_MAX.

EINVAL

An invalid request is specified in the ttv_req field of a tt_vec_t passed to TT_VEC_GENERIC.

EINVAL

Undocumented fields in a tt_vec_t passed to TT_VEC_GENERIC are not 0 (zero).

EINVAL

The ttvr_count or ttvr_ret1 field of a tt_vec_res_t passed to TT_VEC_GENERIC is NULL.

EINVAL

The size argument to a TT_PROC_GET_PATHNAME is larger than MAXPATHLEN.

ENODATA

Data in this register is not readable or not writable at this time.

ENOENT

The directory portion of the core file argument to a TT_PROC_CORE request does not exist.

ENOMEM

System is out of memory.

EPROTO

Attempting to stop a thread already stopped by the debugger.

EPROTO

Attempting to resume a thread not stopped by the debugger.

EPROTO

Attempting to read or write registers while the thread is not stopped.

EPROTO

Attempting to obtain the state of a thread which was not stopped by the debugger.

EPROTO

Invoked before an exec event took place (TT_PROC_GET_PATHNAME).

EPROTO

The process is exiting and the request is not allowed in this condition.

EPROTO

The debugger is attempting to modify wide registers after having modified narrow registers.

EPROTO

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 modified before the vfork.

ESRCH

pid and/or lwpid identify a process or a thread to be traced that does not exist or has not executed a ttrace() with the TT_PROC_SETTRC 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_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 TT_LWP_CONTINUE or TT_LWP_SINGLE request is not TT_NOPC, 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

ttrace was developed by HP.

STANDARDS CONFORMANCE

ttrace(): LOCAL

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© 1983-2007 Hewlett-Packard Development Company, L.P.