UFT 探针管理器
uft(即用户函数跟踪)探针管理器支持调查在进程的 XCOFF 符号表中可视的用户空间函数。 uft 探针管理器支持源代码为 C 或 FORTRAN 语言文本文件的函数入口和出口点的探针点,即使符号表可包含源代码为非 C 或 FORTRAN 语言的符号。
从用户角度看, Java™ 应用程序的跟踪方式与现有跟踪机制相同,而 JVM 代表 Probevue 执行大部分实际任务。
uft 探针管理器接受以下格式的 5 重调查规范:
uft:<processID>:*:<function_name>:<entry|exit>
- 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>/"。
/* 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 使用基于 ptrace 或 procfs 的 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" 选项一起提供。