Gestionnaire de sondes UFT

Le gestionnaire de sondes de traçage des fonctions utilisateur ou uft prend en charge les fonctions d'analyse de l'espace utilisateur qui sont visibles dans la table de symboles XCOFF d'un processus. Le gestionnaire de sondes uft prend en charge les points de sonde qui se trouvent aux points d'entrée et de sortie des fonctions dont la source est un fichier texte en langage C ou FORTRAN, même si la table de symboles peut contenir des symboles dont les sources proviennent d'une langue autre que C ou FORTRAN.

Le traçage des applications Java™ est identique au mécanisme de traçage existant du point de vue des utilisateurs et la machine virtuelle Java est celle qui effectue la plupart des tâches réelles pour le compte de Probevue.

Le gestionnaire de sondes uft accepte une spécification de sonde à 5 tuples au format suivant:

uft:<processID>:*:<function_name>:<entry|exit>
Remarque: Le gestionnaire de sondes uft requiert l'ID de processus pour le processus à tracer et le nom de fonction complet de la fonction au point d'entrée ou de sortie duquel la sonde doit être placée.
PID ou nom de programme

Indique l'ID du processus à tracer ou le nom du programme (nom du fichier exécutable) à analyser. Vous pouvez fournir l'ID de processus ou le nom du fichier exécutable entre guillemets ("/usr/bin/test") ou entre guillemets ('/usr/bin/test') ou en tant que chemin de fichier (/usr/bin/test). Vous pouvez indiquer le chemin d'accès absolu ou relatif du fichier exécutable. Vous pouvez également fournir le lien fixe ou le lien symbolique vers le fichier exécutable en tant que valeur du paramètre de nom de programme. Les exemples suivants montrent différentes manières de spécifier la deuxième spécification de sonde de tuple.

Exemples

@@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 
Si /usr/bin/test est le fichier exécutable et /testln est le lien lointain vers le fichier /usr/bin/test (/testln ->/usr/bin/test), exécutez la commande suivante pour sonder tous les processus qui ont été démarrés en exécutant le fichier exécutable /usr/bin/test ou le lien lointain /testln pour cet utilisateur.

@@uft:/testln:*:foo:entry  
Remarque: à la fois, un utilisateur peut tracer un exécutable en utilisant une seule session.

Lorsque la troisième zone est définie sur *, le gestionnaire de sondes UFT recherche la fonction dans tous les modules chargés dans l'espace adresse du processus, y compris l'exécutable principal et les modules partagés. Cela implique que si un programme contient plus d'une fonction C portant ce nom (par exemple, des fonctions de classe statique contenues dans des modules d'objets différents), des sondes seront appliquées au point d'entrée de chacune de ces fonctions.

Si un nom de fonction d'un module spécifique doit être vérifié, le nom du module doit être spécifié dans la troisième zone. La syntaxe de spécification de sonde permettant de fournir le nom du module de bibliothèque est illustrée ci-dessous:

# 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	  

Le nom de fonction dans le quatrième tuple peut être spécifié en tant qu'expression régulière étendue (ERE). L'élément ERE doit être placé entre "/ et /" comme "/ < ERE> /".

Lorsque le nom de fonction est spécifié en tant que ERE, toutes les fonctions correspondant à l'expression régulière spécifiée dans le module spécifié sont vérifiées.
 /* 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

Dans les sondes d'entrée, où un nom de fonction est spécifié en tant qu'expression régulière, les arguments individuels ne sont pas accessibles. Toutefois, la fonction probevue print_args peut être utilisée pour imprimer le nom de la fonction et ses arguments. Les valeurs d'argument sont imprimées en fonction des informations de type d'argument disponibles dans la table de trace de la fonction.

Dans les sondes d'exit, où un nom de fonction est spécifié en tant qu'expression régulière, la valeur de retour est inaccessible.

Probevue prend en charge l'activation de sondes dans plusieurs processus à la fois. Toutefois, vous aurez besoin de privilèges, même pour les processus de sondage qui vous appartiennent.

Probevue applique une restriction qui empêche le débogage des processus avec des sondes d'espace utilisateur à l'aide des API ptrace ou procfs .

Comme indiqué ci-dessus, le gestionnaire de sondes uft prend en charge les sondes dans les modules partagés tels que les modules de bibliothèque partagée. Le script suivant montre un exemple qui trace l'activité de mutex en activant des sondes dans les sous-routines de verrouillage et de déverrouillage de mutex de la bibliothèque d'unités d'exécution.

/* 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);
}
  • L'utilisateur doit mapper les types de données Fortran aux types de données ProbeVue et les utiliser dans le script. Le mappage des types de données de base Fortran aux types de données ProbeVue est répertorié dans le tableau ci-dessous.
    Tableau 1. Fortran vers ProveVue
    Type de données Fortran Type de données ProbeVue
    ENTIER * 2 court
    ENTIER * 4 int/long
    ENTIER * 8 long long
    REAL séparer
    DOUBLE PRÉCISION doublon
    complexe Aucun type de données de base équivalent. Il doit être mappé à une structure comme illustré ci-dessous:
    typedef struct complex {
    float a;
    float b;
    } COMPLEX;
    LOGIQUE int (la norme Fortran requiert que les variables logiques soient de la même taille que les variables INTEGER/REAL)
    ALPHANUM char
    BYTE caractère signé
  • Fortran transmet les arguments scalaires IN des procédures internes par valeur et les autres arguments par référence. Les arguments transmis par référence doivent être accessibles avec copy_userdata (). Pour plus d'informations sur l'association d'arguments dans fortran, voir la rubrique Association d'arguments .
  • Les noms de routine dans un programme Fortran sont sensibles à la casse. Cependant, tout en les spécifiant dans un script ProbeVue , ils doivent être en minuscules.
    L'exemple de script suivant montre comment mapper des types de données Fortran à des types de données 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 stocke les tableaux sous forme de colonnes majeures, tandis que ProbeVue stocke sous forme de lignes majeures et le script ci-dessous montre comment les utilisateurs peuvent extraire les éléments de tableau.
    /* 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
  • Les fonctions intrinsèques ou intégrées ne peuvent pas être vérifiées avec ProbeVue . Toutes les routines FORTRAN répertoriées dans la table de symboles XCOFF des bibliothèques exécutables / liées peuvent être vérifiées. ProbeVue utilise la table de symboles XCOFF pour identifier l'emplacement de ces routines. Toutefois, le prototype de la routine doit être fourni par l'utilisateur et ProbeVue tente d'accéder aux arguments en fonction du prototype fourni. Pour les routines dans lesquelles le compilateur code les noms de routine, le nom de la routine doit être fourni. Etant donné que Vue est un langage de style C, l'utilisateur doit s'assurer que le prototype de fonction / sous-routine FORTRAN est correctement mappé au prototype de fonction de style de langage C. Reportez-vous aux conventions de liaison pour la transmission d'arguments et les valeurs de retour de fonction dans la rubrique Transmission de données d'une langue à une autre . L'exemple suivant illustre ceci:
    /* 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 ne prend pas en charge l'inclusion directe des fichiers d'en-tête Fortran dans le script. Toutefois, un mappage des types de données Fortran aux types de données ProbeVue peut être fourni dans un fichier d'en-tête ProbeVue et inclus avec l'option "-I'".