UFT 探针管理器

uft(即用户函数跟踪)探针管理器支持调查在进程的 XCOFF 符号表中可视的用户空间函数。 uft 探针管理器支持源代码为 C 或 FORTRAN 语言文本文件的函数入口和出口点的探针点,即使符号表可包含源代码为非 C 或 FORTRAN 语言的符号。

从用户角度看, Java™ 应用程序的跟踪方式与现有跟踪机制相同,而 JVM 代表 Probevue 执行大部分实际任务。

uft 探针管理器接受以下格式的 5 重调查规范:

uft:<processID>:*:<function_name>:<entry|exit>
注: uft 探针管理器需要要跟踪的进程的进程标识以及要将探针置于其入口或出口点的函数的完整函数名。
PID 或程序名

指定要跟踪的进程的进程标识或要探测的程序的名称 (可执行文件的名称)。 可以使用双引号 ("/usr/bin/test") 或单引号 ('/usr/bin/test') 或作为文件路径 (/usr/bin/test) 提供进程标识或可执行文件的名称。 您可以提供可执行文件的绝对路径或相对路径。 您还可以提供指向可执行文件的硬链接或符号链接作为程序名参数的值。 以下示例显示了指定第二个元组探针规范的不同方法。

示例

@@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 
如果 /usr/bin/test 是可执行文件,而 /testln 是指向 /usr/bin/test 文件 (/testln ->/usr/bin/test) 的软链接,请运行以下命令以探测通过对该用户运行 /usr/bin/test 可执行文件或 /testln 软链接启动的所有进程。

@@uft:/testln:*:foo:entry  
注: 一次用户只能使用一个会话来跟踪可执行文件。

当第三个字段设为 * 时,UFT 探针管理器在装入到进程地址空间的所有模块(包括主要的可执行模块和共享模块)中搜索函数。 这意味着如果程序包含具有此名称的多个 C 函数(例如,在不同对象模块中包含的具有静态类的函数),那么调查将应用于这些函数的每一个的入口点。

如果需要调查特定模块中的函数名,那么需要在第三个字段中指定模块名。 以下说明提供库模块名的调查规范语法:

# 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	  

第四个元组中的函数名可以指定为扩展的正则表达式 (ERE)。 ERE 应该包含在 "//" 之间,例如 "/<ERE>/"

当函数名指定为 ERE 时,将调查指定模块中与指定正则表达式匹配的所有函数。
 /* 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

在函数名指定为正则表达式的入口调查中,无法访问个别参数。 但是,probevue 函数 print_args 可以用于显示函数名及其参数。 将根据函数的可跟踪表中可用的参数类型信息来显示参数值。

在函数名指定为正则表达式的出口调查中,无法访问返回值。

Probevue 支持同时在多个进程中启用调查。 但是,即使是属于您的调查进程,您也需要特权。

Probevue 使用基于 ptraceprocfs 的 API 来实施一个限制,即防止调试具有用户空间调查的进程。

如上所述,uft 探针管理器支持共享模块(如共享库模块)中的调查。 以下脚本显示了通过在线程库的 mutex lock 和 unlock 子例程中启用调查来跟踪 mutex 活动的示例。

/* 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);
}
  • 用户必须将 Fortran 数据类型映射到 ProbeVue 数据类型,并在脚本中使用相同的数据类型。 下表列出了 Fortran 基本数据类型到 ProbeVue 数据类型的映射。
    表 1. Fortran 至 ProveVue 数据类型映射
    Fortran 数据类型 ProbeVue 数据类型
    INTEGER * 2 简短
    INTEGER * 4 int/long
    INTEGER * 8 long long
    REAL float
    DOUBLE PRECISION double
    COMPLEX 没有等效的基本数据类型。 这需要映射到一个结构,如下所示:
    typedef struct complex {
    float a;
    float b;
    } COMPLEX;
    LOGICAL int (Fortran 标准需要逻辑变量的大小与 INTEGER/REAL 变量相同)
    CHARACTER char
    BYTE 有符号字符型
  • Fortran 按值传递内部过程的 IN 标量参数,而其他参数按引用传递。 应该使用 copy_userdata () 访问由引用传递的参数。 可以在 自变量关联 主题中找到有关 fortran 中的自变量关联的更多信息。
  • Fortran 程序中的例程名不区分大小写。 但是,在 ProbeVue 脚本中指定它们时,它们应该为小写。
    以下样本脚本说明如何将 Fortran 数据类型映射到 ProbeVue 数据类型:
    /* 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 以列主格式存储数组,而 ProbeVue 以行主格式存储数组,以下脚本显示用户如何检索数组元素。
    /* 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
  • 无法使用 ProbeVue 来探测内部或内置函数。 可以调查如可执行/链接的库中 XCOFF 符号表中列出的所有 FORTRAN 例程。 ProbeVue 使用 XCOFF 符号表标识这些例程的位置。 但是,例程的原型必须由用户提供,并且 ProbeVue 会尝试根据提供的原型访问自变量。 对于编译器于修饰其例程名的例程,应该提供修饰的名称。 因为 Vue 是 C 式语言,所以用户应该确保 FORTRAN 函数/子例程原型适当的映射到 C 语言式函数原型。 请参阅 将数据从一种语言传递到另一种语言 主题中的参数传递和函数返回值的链接约定。 以下示例说明此内容:
    /* 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 不支持在脚本中直接包含 Fortran 头文件。 但是, Fortran 数据类型到 ProbeVue 数据类型的映射可以在 ProbeVue 头文件中提供,并随 "-I" 选项一起提供。