Linux and UNIX Man Pages

Linux & Unix Commands - Search Man Pages

ttrace(2) [hpux man page]

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