unixdev.net


Switch to SpeakEasy.net DSL

The Modular Manual Browser

Home Page
Manual: (HP-UX-11.11)
Page:
Section:
Apropos / Subsearch:
optional field



 ttrace(2)							   ttrace(2)




 NAME
      ttrace - tracing facility for multithreaded processes

 SYNOPSIS
      #include <&lt&lt&lt;sys/ttrace.h>&gt&gt&gt;

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

      The request argument determines the action to be taken by ttrace() and
      is one of the following:

      TT_PROC_SETTRC This request must be issued by a child process if it is
		     to be traced by its parent.

		     For this request, the pid, lwpid, addr, and addr2
		     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 that it is critical for future backward
		     compatibility that the TT_VERSION macro itself be used
		     and not its value.

      All other requests are to be used only by the tracing process.  They
      are divided in two groups: requests that target a process and requests
      that target a specific thread within the process.	 For all process-
      wide requests (those prefixed by TT_PROC_), pid is the process ID of
      the traced process and lwpid must be set to zero.





 Hewlett-Packard Company	    - 1 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




      The process-wide requests are:

      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
		     effective user ID of the tracing process is super-user.

		     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 lwpid and addr2 arguments
		     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_RDDATA These requests allow reading from the target process
		     text (TT_PROC_RDTEXT) or data space (TT_PROC_RDDATA).

		     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.





 Hewlett-Packard Company	    - 2 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




		     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.








 Hewlett-Packard Company	    - 3 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




		     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/or
		     threads.  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_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



 Hewlett-Packard Company	    - 4 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




		     ttstate_t data structure in 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;
				    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



 Hewlett-Packard Company	    - 5 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




			 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 or TTEVT_VFORK
		     event is as follows:

			  typedef struct {
			       pid_t   tts_fpid;
			       lwpid_t tts_flwpid;
			       int     tts_isparent;
			  } ttfork_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_isparent is zero for the child event and one for
		     the parent.

		     The data associated with a TTEVT_SIGNAL event is as
		     follows:

			  typedef struct {
			       int	       tts_signo;
			       ttsigf_t	       tts_sigflags;



 Hewlett-Packard Company	    - 6 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




			       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:

			  typedef struct {
			       int	   tts_isbpt;



 Hewlett-Packard Company	    - 7 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




			  } 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).

      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



 Hewlett-Packard Company	    - 8 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




		     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 in the target process's current working
		     directory. The core file is named core.pid where pid is
		     the process ID of the target process. The process's
		     state is left unchanged.  The lwpid, addr, data and
		     addr2 arguments must be zero.

      All other requests, except non debug-related requests below, are
      targeted to a specific thread in the traced process.  Also, all other
      requests require both the pid of the traced process and an lwpid
      specifying a valid thread in the process being traced.  These requests
      are prefixed by TT_LWP_ and are as follows:

      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.





 Hewlett-Packard Company	    - 9 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




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

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

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

 EVENTS
      As noted earlier, a tracing process can set event flags in the context



 Hewlett-Packard Company	   - 10 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




      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



 Hewlett-Packard Company	   - 11 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




			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_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 and 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.




 Hewlett-Packard Company	   - 12 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




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

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



 Hewlett-Packard Company	   - 13 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




      Otherwise, execution resumes from the point where it was interrupted.

      Additional requests are available:

      TT_LWP_RUREGS	  With this request, the words at offset addr in the
			  save_state structure are returned to the tracing
			  process.  The data argument is the size of the
			  read.	 The addr2 argument points to the location
			  in the debugger space where the data will be
			  written.  The addr argument must be word-aligned
			  and addr+data must be less or equal to sizeof
			  (save_state_t) (see <&lt&lt&lt;machine/save_state.h>&gt&gt&gt;).

			  NOTE: Only 4 and 8 bytes reads and writes are
			  currently supported.

      TT_LWP_WUREGS	  With this request, 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: Only 4 and 8 bytes reads and writes are
			  currently supported.

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

	   [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_WRTEXT).

	   [EINVAL]	  Invalid signal (TT_LWP_CONTINUE, TT_LWP_SINGLE).

	   [EINVAL]	  Invalid offset (TT_LWP_RUREGS, TT_LWP_WUREGS).





 Hewlett-Packard Company	   - 14 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




	   [EINVAL]	  ptrace() and ttrace() requests are being mixed.

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

	   [EINVAL]	  An invalid register is targeted by TT_LWP_WUREGS.

	   [EINVAL]	  The size argument to a TT_PROC_GET_PATHNAME is
			  larger than MAXPATHLEN.

	   [EACCES]	  The pid argument to the TT_PROC_ATTACH is the pid
			  of the invoker.

	   [EACCES]	  The process is already being traced.

	   [EACCES]	  Attempting to trace a process whose binary resides
			  on a soft/interruptible NFS mount point.

	   [EACCES]	  The executable image of the process being attached
			  resides across an interruptible NFS mount.

	   [EFAULT]	  Invalid user address.

	   [EPERM]	  The specified thread cannot be attached for
			  tracing.

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

	   [EINTR]	  Cannot suspend process or attach is interrupted
			  (TT_PROC_ATTACH).

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




 Hewlett-Packard Company	   - 15 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




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

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

	   [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).

	   [ENOMEM]	  System is out of memory.

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

 EXAMPLE
      A simple no-frills system call tracer:

      #include <stdio.h>
      #include <stdlib.h>
      #include <errno.h>
      #include <sys/ttrace.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;
      }




 Hewlett-Packard Company	   - 16 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




      static char *
      ev_name(ttevents_t ev)
      {
	      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",



 Hewlett-Packard Company	   - 17 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




		      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",
		      SYS_sigvector,	      "sigvec",
		      -1,		      NULL,
	      };

	      if (stp->tts_scno == SYS_siginhibit || stp->tts_scno == SYS_sigenable) {
		      return;
	      }
	      if (evt == TTEVT_NONE) {
		      evt = TTEVT_SYSCALL;



 Hewlett-Packard Company	   - 18 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




	      }
	      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),



 Hewlett-Packard Company	   - 19 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




				    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");



 Hewlett-Packard Company	   - 20 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




			      }
			      /* 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;
      }

 AUTHOR
      ttrace was developed by HP.





 Hewlett-Packard Company	   - 21 -   HP-UX Release 11i: November 2000






 ttrace(2)							   ttrace(2)




 SEE ALSO
      adb(1), fork(2), vfork(2), exec(2), signal(2), wait(2),
      ttrace_wait(2).

 STANDARDS CONFORMANCE
      ttrace(): LOCAL
















































 Hewlett-Packard Company	   - 22 -   HP-UX Release 11i: November 2000