UFT プローブ・マネージャー

uft (ユーザー関数トレース) プローブ・マネージャーは、プロセスの XCOFF シンボル・テーブルに表示されるユーザー・スペース関数をプローブすることをサポートしています。 uft プローブ・マネージャーは、ソースが C または FORTRAN 言語のテキスト・ファイルである関数の入り口点および出口点であるプローブ・ポイントをサポートします。ただし、シンボル・テーブルには、 C または FORTRAN以外の言語からのソースを持つシンボルが含まれている場合があります。

Java™ アプリケーションのトレースは、ユーザーの観点からは既存のトレース・メカニズムと同じ方法で行われます。JVM は、Probevue の代わりに実タスクのほとんどを実行するものです。

UFT プローブ・マネージャーは、次のフォーマットの 5 組のプローブ指定を受け入れます。

uft:<processID>:*:<function_name>:<entry|exit>
注: uft プローブ・マネージャーでは、トレースするプロセスのプロセス ID と、プローブを配置するエントリー・ポイントまたはエグジット・ポイントを持つ関数の完全な関数名が必要です。
PID またはプログラム名

トレースするプロセスのプロセス ID、または厳密に調べるプログラムの名前 (実行可能ファイルの名前)。 プロセス ID または実行可能ファイルの名前は、二重引用符 ("/usr/bin/test") または単一引用符 ('/usr/bin/test') で囲んで指定するか、ファイル・パス (/usr/bin/test) として指定することができます。 実行可能ファイルの絶対パスまたは相対パスを指定できます。 また、実行可能ファイルへのハード・リンクまたはシンボリック・リンクを、値としてプログラム名パラメーターに指定することもできます。 以下の例は、2 番目のタプル・プローブ仕様を指定するための、さまざまな方法を示しています。


@@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  
注: ユーザーは一度に 1 つのセッションのみを使用して実行可能ファイルをトレースできます。

3 番目のフィールドを * に設定すると、UFT プローブ・マネージャーは、プロセスのアドレス・スペースにロードされるすべてのモジュール (メインの実行可能モジュールと共有モジュールを含む) で関数を検索します。 これは、1 つのプログラムにこの名前の C 関数が複数含まれている場合、(例えば、複数の異なるオブジェクト・モジュールに静的クラスをもつ関数が含まれている場合)、プローブがこれらのすべての関数のエントリー・ポイントに適用されることを意味します。

特定のモジュール内の関数名をプローブする必要がある場合、そのモジュール名を 3 番目のフィールドに指定する必要があります。 ライブラリー・モジュール名を指定するプローブ指定構文を以下に示します。

# 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	  

4 番目の組の関数名を拡張正規表現 (ERE) として指定できます。 The ERE should be enclosed between "/ and /" like "/<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 ロックおよびアンロック・サブルーチンのプローブを使用可能にして、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 signed char
  • 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」オプションを使用して組み込むことができます。