UFT probe manager

The uft or the user function tracing probe manager supports probing user space functions that are visible in the XCOFF symbol table of a process. The uft probe manager supports probe points that are at entry and exit points of functions whose source is a C or FORTRAN language text file even though the symbol table can contain symbols whose sources are from a language other than C or FORTRAN.

The tracing of Java™ applications in a way identical to the existing tracing mechanism from the users point of view and the JVM is one that performs most of the real tasks on behalf of Probevue.

The uft probe manager accepts a 5-tuple probe specification in the following format:

uft:<processID>:*:<function_name>:<entry|exit>
Note: The uft probe manager requires the process ID for the process to be traced and the complete function name of the function at whose entry or exit point the probe is to be placed.
PID or program name

Specifies process ID of the process to be traced or the name of the program (name of the executable file) to be probed. You can provide the process ID or the name of the executable file in double quotes ("/usr/bin/test") or in single quotes('/usr/bin/test') or as a file path (/usr/bin/test) . You can provide the absolute path or the relative path of the executable file. You can also provide the hard link or the symbolic link to the executable file as a value to the program name parameter. The following examples show different ways to specify the second tuple probe specification.

Examples

@@uft:123450 :*: foo :entry
@@uft : /usr/bin/test:* :foo:entry
@@uft:./test:*:foo:entry
@@uftxlc++:/usr/bin/test:*:foo:exit
@@uftxlc++:"/usr/bin/testxxx":*:foo:exit
@@uft :"/usr/bin/xxx":* :foo:entry
@@uft:'/home/xxx/test':*:func1:entry 
If /usr/bin/test is the executable file and /testln is the soft link to the /usr/bin/test file (/testln ->/usr/bin/test), run the following command to probe all processes that were started by running the /usr/bin/test executable file or the /testln soft link for that user.

@@uft:/testln:*:foo:entry  
Note: At a time a user can trace an executable by using one session only.

When the third field is set to *, the UFT probe manager searches the function in all of the modules loaded into the process address space including the main executable and shared modules. This implies that if a program contains more than one C function with this name (for example, functions with static class that are contained in different object modules), then probes will be applied to the entry point of every one of these functions.

If a function name in a specific module needs to be probed, the module name needs to be specified in the third field. The probe specification syntax to provide the library module name is illustrated below:

# Function foo in any module
@@uft:<pid>:*:foo:entry 
# Function foo in any module in any archive named libc.a
@@uft:<pid>:libc.a:foo:entry 
# Function foo in the shr.o module in any archive named libc.a
@@uft:<pid>:libc.a(shr.o):foo:entry	  

The function name in the fourth tuple can be specified as an Extended Regular Expression (ERE). The ERE should be enclosed between "/ and /" like "/<ERE>/".

When the function name is specified as an ERE, all the functions matching the specified regular expression in the specified module is probed.
 /* Probe entry of all libc.a functions starting with “malloc” word */
@@uft:$__CPID:libc.a: “/^malloc.*/”:entry      
/* Probe exit of all functions in the executable a.out */
@@uft:$__CPID:a.out:”/.*/”:exit

In the entry probes, where a function name is specified as a regular expression, individual arguments cannot be accessed. However, probevue function print_args can be used to print the function name and its arguments. The argument values is printed based on the argument type information available in the traceback table of the function.

In the exit probes, where a function name is specified as a regular expression, return value cannot be accessed.

Probevue supports enabling probes in more than one process at the same time. However, you will need privileges even for probing processes that belong to you.

Probevue enforces a restriction that prevents processes with user-space probes from being debugged using the ptrace or procfs based APIs.

As indicated above, the uft probe manager supports probes in shared modules like shared library modules. The following script shows an example that traces mutex activity by enabling probes in the thread library's mutex lock and unlock subroutines.

/* pthreadlocks.e */
/* Trace pthread mutex activity for a given multithreaded process */
/* The following defines are from /usr/include/sys/types.h */

typedef long long pid_t;
typedef long long thread_t;

typedef struct {
	int	__pt_mutexattr_status;	
	int	__pt_mutexattr_pshared;	
	int	__pt_mutexattr_type;
} pthread_mutexattr_t;

typedef struct __thrq_elt thrq_elt_t;

struct __thrq_elt {
	thrq_elt_t	*__thrq_next;
	thrq_elt_t	*__thrq_prev;
};

typedef volatile unsigned char _simplelock_t;

typedef struct __lwp_mutex {
	char		__wanted;
	_simplelock_t	__lock;
} lwp_mutex_t;

typedef struct {
	lwp_mutex_t		__m_lmutex;
	lwp_mutex_t		__m_sync_lock;
	int			__m_type;
	thrq_elt_t		__m_sleepq;
	int			__filler[2];
} mutex_t;

typedef struct {
	mutex_t			__pt_mutex_mutex;
	pid_t			__pt_mutex_pid;
	thread_t		__pt_mutex_owner;
	int			__pt_mutex_depth;
	pthread_mutexattr_t	__pt_mutex_attr;
} pthread_mutex_t;

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

@@uft:$__CPID:*:pthread_mutex_lock:entry
{
	printf("thread %d: mutex 0x%08x locked\n", __tid, __arg1);
}

@@uft:$__CPID:*:pthread_mutex_unlock:entry
{
	printf("thread %d: mutex 0x%08x unlocked\n", __tid, __arg1);
}
  • User has to map the Fortran data types to ProbeVue data types and use the same in the script. The mapping of Fortran basic data types to ProbeVue data types is listed in the below table.
    Table 1. Fortran to ProveVue data types mapping
    Fortran data-type ProbeVue data-type
    INTEGER * 2 short
    INTEGER * 4 int/long
    INTEGER * 8 long long
    REAL float
    DOUBLE PRECISION double
    COMPLEX No equivalent basic data type. This needs to be mapped to a structure as shown below:
    typedef struct complex {
    float a;
    float b;
    } COMPLEX;
    LOGICAL int (The Fortran standard requires logical variables to be the same size as INTEGER/REAL variables)
    CHARACTER char
    BYTE signed char
  • Fortran passes IN scalar arguments of internal procedures by value, and other arguments by reference. Arguments passed by reference should be accessed with copy_userdata(). More information on argument association in fortran can be found in the Argument association topic.
  • Routine names in a Fortran program is case in-sensitive. But, while specifying them in a ProbeVue script, they should be in lower-case .
    The following sample script illustrates how to map Fortran data types to ProbeVue data types:
    /* cmp_calc.e */
    /* Trace fortran routines 
    cmp_calc(COMPLEX, INTEGER) and 
    cmplxd(void) */
    
    typedef struct complex{
            float a;
            float b;
            } COMPLEX;
    
    typedef int INTEGER;
    
    /* arguments are indicated to be of pointer type as they are passed by reference */
    void cmp_calc(COMPLEX *, INTEGER *);  
    void cmplxd();
    
    @@uft:$__CPID:*:cmplxd:entry
    {
    printf("In cmplxd entry \n");
    }
    
    @@uft:$__CPID:*:cmp_calc:entry
    {
    COMPLEX c;
    int i;
    copy_userdata(__arg1, c);
    copy_userdata(__arg2, i);
    printf("%10.7f+j%9.7f  %d \n", c.a,c.b,i);
    }
  • Fortran stores arrays in column-major form, whereas ProbeVue stores in row-major form and the below script shows how users can retrieve the array elements.
    /* array.e*/
    /* ProbeVue script to probe fortran program array.f */
    
    void displayarray(int **, int, int);
    @@uft:$__CPID:*:displayarray:entry
    {
    int a[5][4];		/* row and column sizes are interchanged */
    copy_userdata(__arg1, a);
    /* to print the first row */
    printf("%d %d %d \n”, a[0][0], a[1][0], a[2][0]);
    /* to print the second row */
    printf(“%d %d %d\n", a[0][1], a[1][1], a[2][1]);
    }
    
    /* Fortran program array.f */
    
    PROGRAM ARRAY_PGM
    IMPLICIT NONE 
    INTEGER, DIMENSION(1:4,1:5) :: Array 
    INTEGER :: RowSize, ColumnSize
    CALL ReadArray(Array, RowSize, ColumnSize) 
    CALL DisplayArray(Array, RowSize, ColumnSize) 
    CONTAINS
    SUBROUTINE ReadArray(Array, Rows, Columns)
    IMPLICIT NONE
    INTEGER, DIMENSION(1:,1:), INTENT(OUT) :: Array
    INTEGER, INTENT(OUT) :: Rows, Columns
    INTEGER :: i, j
    READ(*,*) Rows, Columns
    DO i = 1, Rows
    READ(*,*) (Array(i,j), j=1, Columns)
    END DO
    END SUBROUTINE ReadArray
    SUBROUTINE DisplayArray(Array, Rows, Columns) 
    IMPLICIT NONE 
    INTEGER, DIMENSION(1:,1:), INTENT(IN) :: Array
    INTEGER, INTENT(IN) :: Rows, Columns 
    INTEGER :: i, j 
    DO i = 1, Rows 
    WRITE(*,*) (Array(i,j), j=1, Columns )
    END DO 
    END SUBROUTINE DisplayArray
    END PROGRAM ARRAY_PGM
  • Intrinsic or built-in functions cannot be probed with ProbeVue . All FORTRAN routines as listed in the XCOFF symbol table of the executable/linked libraries can be probed. ProbeVue uses the XCOFF symbol table to identify the location of these routines. However, the prototype for the routine has to be provided by the user and ProbeVue tries to access the arguments according to the prototype provided. For routines where the compiler mangles the routine names, the mangled name should be provided. Since Vue is a C-style language, user should ensure that the FORTRAN function/subroutine prototype is appropriately mapped to C language style function prototype. Please refer to the linkage conventions for argument passing and function return values in the Passing data from one language to another topic. The below example illustrates this:
    /* Fortran program ext_op.f */
    /* Operator “*” is extended for rational multiplication */
    MODULE rational_arithmetic
    IMPLICIT NONE
            TYPE RATNUM
                    INTEGER :: num, den
            END TYPE RATNUM
            INTERFACE OPERATOR (*)
                    MODULE PROCEDURE rat_rat, int_rat, rat_int
            END INTERFACE
            CONTAINS
            FUNCTION rat_rat(l,r)      ! rat * rat
                    TYPE(RATNUM), INTENT(IN) :: l,r
                    TYPE(RATNUM) :: val,rat_rat
                    val.num=l.num*r.num
                    val.den=l.den*r.den
                    rat_rat=val
            END FUNCTION rat_rat
            FUNCTION int_rat(l,r)      ! int * rat
                    INTEGER, INTENT(IN)      :: l
                    TYPE(RATNUM), INTENT(IN) :: r
                    TYPE(RATNUM) :: val,int_rat
                    val.num=l*r.num
                    val.den=r.den
                    int_rat=val
            END FUNCTION int_rat
            FUNCTION rat_int(l,r)      ! rat * int
                    TYPE(RATNUM), INTENT(IN) :: l
                    INTEGER, INTENT(IN)      :: r
                    TYPE(RATNUM) :: val,rat_int
                    val.num=l.num*r
                    val.den=l.den
                    rat_int=val
            END FUNCTION rat_int
    END MODULE rational_arithmetic
    PROGRAM Main1
    Use rational_arithmetic
    IMPLICIT NONE
    	TYPE(RATNUM) :: l,r,l1
    	l.num=10
            l.den=11
            r.num=3
            r.den=4
            L1=l*r
    END PROGRAM Main1
    
    /* ext_op.e */
    /* ProbeVue script to probe routine that gets called when “*”
        is used to multiply rational numbers in ext_op.f */
    
    struct rat
    {
            int num;
            int den;
    };
    struct rat rat;
    void __rational_arithmetic_NMOD_rat_rat(struct rat*,
    	struct rat*,struct rat*); 
    /* Note that the mangled function name is provided. */    
    /* Also, the structure to be returned is sent in the buffer whose address is provided as the first argument. */
    /* The first explicit parameter is in the second argument. */
    @@BEGIN
    {
            struct rat* rat3;
    }
    @@uft:$__CPID:*:__rational_arithmetic_NMOD_rat_rat:entry
    {
    	struct rat rat1,rat2;
            copy_userdata((struct rat *)__arg2,rat1);
            copy_userdata((struct rat *)__arg3,rat2);
            rat3=__arg1;
    	/* The address of the buffer where the returned structure will be stored is saved at the function entry */
            printf("Argument Passed rat_rat = %d:%d,%d:%d\n",rat1.num,rat1.den,rat2.num,rat2.den);
    }
    @@uft:$__CPID:*:__rational_arithmetic_NMOD_rat_rat:exit
    {
            struct rat rrat;
            copy_userdata((struct rat *)rat3,rrat);	
            /* The saved buffer address is used to fetch the returned structure */
            printf("Return from rat_rat = %d:%d\n",rrat.num,rrat.den);
            exit();
    }
  • ProbeVue won’t support direct inclusion of Fortran header files in the script. However, a mapping of Fortran data types to ProbeVue data types can be provided in a ProbeVue header file and included with the “-I’’ option.