Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
ttrace(2)		      System Calls Manual		     ttrace(2)

NAME
       ttrace -	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 ex-
       ecution of another process.  Its	primary	use is for the	implementation
       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

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

       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 argu-
		      ments 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 that	it is critical for future backward compatibil-
		      ity that the 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 pid is the process ID of the	traced process
       and lwpid must be set to	zero.

       The process-wide	requests are:

       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 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_DE-
		      TACH_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 (see	above).

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

		      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
		      or 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 de-
		      bug another debugger.  The and options allow  events  to
		      be  inherited  by	child processes	and/or threads.	 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
		      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 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	estab-
		      lished  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 re-
		      garding 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.

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

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

		      The data associated with a event is as follows:

		      is the signal number.

		      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:

		      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 IPF:

       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  re-
		      turn  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 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 un-
		      changed.	The lwpid, addr, data and addr2	arguments must
		      be zero.

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

		      The  available  breakpoint  registers must be shared be-
		      tween 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.

		      This does	not limit the number of	instructions that  may
		      be present in the	program	text.

		      These  requests are not supported	on PA-RISC versions 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 de-
		      bugger memory.  data must	be 16 bytes.  The request will
		      get the value of the pair	of instruction or data	break-
		      point registers addr and addr+1.

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

       This request returns a pointer to the argument list passed to the
		      initial thread of	the process at execve(2) time.	 (i.e.
		      argc,  argv,  envp)  If the target process has not over-
		      written these arguments, this address can	be used	to re-
		      trieve the full argument and environment list.

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

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

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

       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 instruction	 is  executed.
	      It causes	a flag to be set so that an interrupt occurs upon com-
	      pletion of the next taken	branch instruction, and	then  executes
	      the same steps as	listed above for the TT_LWP_CONTINUE request.

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

	      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.

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

       These requests read per-thread breakpoint values	from breakpoint	regis-
       ters.
	      They are identical to and	respectively in	other respects.

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

       These requests allow the	debugger 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	the tracing process.  The addr	argument  must
	      be 8-byte-aligned	and conform to <= addr < data must be a	multi-
	      ple of 8 bytes, and addr+data must also conform to <=  addr+data
	      <	 As a special case, to retreive	the final NaT collection, addr
	      == and data == is	also accepted.

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

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

       There is	currently only one non debug-related request:

       This call returns the
	      of the operating system and has been introduced to help debugger
	      developpers 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 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.

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

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  re-
       spond to	the event.  When set in	the context of a thread, only the spe-
       cific 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  pid  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  TTEVT_FORK but it is	important to note that
			 the caveats with respect to 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 un-
			 til a call to or an exit (either by a call to or  ab-
			 normally)  takes place. Continuing the	parent process
			 before	the above steps	take place results in  an  er-
			 ror.

       This  event flag	indicates that a traced	thread needs to	notify the de-
       bugger
			 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 and the path may	subse-
			 quently be obtained using the request.

       This event flag indicates that
			 the traced process will notify	the debugger upon  re-
			 turn  of  all	system calls.  The traced process will
			 also provide the following  information:  the	system
			 call  number, its number of arguments and all its ar-
			 guments, its return value and its error return	in the
			 structure.   If  the  system call is a	or and if, re-
			 spectively, the or event is set, only	the  notifica-
			 tion  associated  with	these events is	performed. 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 en-
			 tering	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  re-
			 quested,  SIGTRAP  loses  all	special	meaning. It is
			 highly	recommended that debuggers use this event  in-
			 stead 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  ac-
			 tive 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.

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

       Additional requests are available:

       With this request, on IPF: The register specified by
			   addr	is returned to the tracing process.  The  data
			   argument  is	the size of the	read.  The addr2 argu-
			   ment	points to the location in the  debugger	 space
			   where  the data will	be written.  The addr argument
			   must	be  a  value  defined  by  __uregs_t  in  <ma-
			   chine/sys/uregs.h>.	 On PA-RISC, The words at off-
			   set addr in the structure are returned to the trac-
			   ing	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 than or equal	to (see

			   On IPF, only	8 and 9	byte reads and writes are cur-
			   rently supported.  9	byte reads are valid only  for
			   General Register values.  The NaT bit corresponding
			   to the general register is returned in bit 0	of the
			   9th byte.  On PA-RISC, only 4 and 8 bytes reads and
			   writes are currently	supported.

       With this request, on IPF:
			   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:  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	regis-
			   ters,  and certain bits of the interruption proces-
			   sor status word.

			   On IPF, only	8 and 9	byte writes are	currently sup-
			   ported.   The  9th  byte is used only for writes to
			   static general registers.  Bit 0 of the 9th byte is
			   written to the corresponding	NaT bit.

			   On PA-RISC, only 4 and 8 bytes reads	and writes are
			   currently supported.

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

	      [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 or is	not

	      [EINVAL]	     Size too large for	data transfer.

	      [EINVAL]	     Invalid signal number.

	      [EINVAL]	     Misaligned	request	or not a word multiple

	      [EINVAL]	     Invalid signal

	      [EINVAL]	     Invalid offset

	      [EINVAL]	     and requests are being mixed.

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

	      [EINVAL]	     An	invalid	register is targeted by

	      [EINVAL]	     The size argument to a is larger than

	      [EACCES]	     The pid argument to the is	the  pid  of  the  in-
			     voker.

	      [EACCES]	     The process is already being traced.

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

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

	      [EFAULT]	     Invalid user address.

	      [EPERM]	     The specified thread cannot be attached for trac-
			     ing.

	      [ESRCH]	     pid and/or	lwpid identify a process or  a	thread
			     to	 be traced that	does not exist or has not exe-
			     cuted a with the request.

	      [EINTR]	     Cannot suspend process or attach is interrupted

	      [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

	      [EPROTO]	     The process is exiting and	the request is not al-
			     lowed in this condition.

	      [EPROTO]	     The  debugger is attempting to modify wide	regis-
			     ters 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  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.

AUTHOR
       was developed by	HP.

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

       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",
		       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;
	       }
	       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;
       }

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

STANDARDS CONFORMANCE
								     ttrace(2)

NAME | SYNOPSIS | DESCRIPTION | SECURITY FEATURES | EVENTS | DEPENDENCIES | ERRORS | AUTHOR | EXAMPLE | SEE ALSO | STANDARDS CONFORMANCE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=ttrace&sektion=2&manpath=HP-UX+11.22>

home | help