Администратор тестов UFT
Администратор тестов uft (трассировки пользовательских функций) поддерживает тестирование функций пользовательского пространства, видимых в таблице имен XCOFF процесса. Администратор тестов uft поддерживает только тестовые точки, являющиеся точками входа или выхода и функций с исходным кодом на языках C или FORTRAN, причем в таблице имен могут содержаться идентификаторы с исходным текстом на языках, отличающихся от C или FORTRAN.
С точки зрения пользователя трассировка приложений на Java™ схожа с существующим механизмом трассировки. JVM при этом выполняет большинство задач от имени Probevue.
Администратор тестов uft принимает 5-кортежную спецификацию тестов в следующем формате:
uft:<ИД-процесса>:*:<имя-функции>:<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 с этим именем (например, функции со статическим классом, содержащиеся в различных объектных модулях), то тесты будут применяться к точке входа каждой из этих функций.
Для тестирования функции в модуле необходимо указать название модуля в третьем поле. Синтаксис:
# Функция foo в любом модуле
@@uft:<pid>:*:foo:entry
# Функция foo в любом модуле любого архива с именем libc.a
@@uft:<pid>:libc.a:foo:entry
# Функция foo в модуле shr.o любого архива с именем libc.a
@@uft:<pid>:libc.a(shr.o):foo:entry
Имя функции в четвертой записи можно указать в виде расширенного регулярного выражения (ERE). Выражение ERE необходимо заключить в "/ и /" , например "/<ERE>/".
/* Тестируются точки входа всех функций libc.a, начинающиеся с “malloc” */
@@uft:$__CPID:libc.a: “/^malloc.*/”:entry
/* Тестируются точки выхода всех функций в a.out */
@@uft:$__CPID:a.out:”/.*/”:exit
При тестировании функций, имя которых соответствует регулярному выражению, нельзя получить доступ к параметрам функций. Для вывода функции и ее аргументов можно использовать функцию print_args. Тип аргументов при выводе будет взят из таблицы обратной трассировки.
При тестировании точки выхода функций, имя которых соответствует регулярному выражению, нельзя получить доступ к возвращаемому значению.
Probevue поддерживает включение тестов в нескольких процессах одновременно. Однако потребуются права доступа даже для тестирования собственных процессов.
Probevue вводит ограничение, делающее невозможной отладку процессов с тестами пользовательского пространства с помощью API на основе ptrace или procfs.
Как сказано выше, администратор тестов uft поддерживает тесты в общих модулях, таких как модули общих библиотек. В следующем сценарии показан пример трассировки мьютекс-операции путем включения тестов в функциях блокировки и разблокировки мьютекса библиотеки нити.
/* pthreadlocks.e */
/* Трассировка мьютекс-операции pthread для многонитевого процесса */
/* Следующие определения взяты из /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 short 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 скалярные аргументы внутренних процедур передаются по значению, остальные - по ссылке. Доступ к аргументам, передающимся по ссылке, должен осуществляться с помощью copy_userdata(). Дополнительная информация о связях аргументов в языке Fortran приведена в разделе Связи аргументов.
- Названия процедур в Fortran не учитывают регистр символов. Но в сценарии ProbeVue имена данных процедур необходимо указывать в нижнем регистре. Следующий пример демонстрирует связь между типами данных Fortran и ProbeVue:
/* cmp_calc.e */ /* Трассировка процедур Fortran cmp_calc(COMPLEX, INTEGER) и cmplxd(void) */ typedef struct complex{ float a; float b; } COMPLEX; typedef int INTEGER; /* в качестве аргументов используются указатели, передаваемые по ссылке */ void cmp_calc(COMPLEX *, INTEGER *); void cmplxd(); @@uft:$__CPID:*:cmplxd:entry { printf("На входе cmplxd \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 хранит массивы с помощью развертывания по столбцам (column-major), а ProbeVue - с помощью развертывания по строкам (row-major). Ниже представлен пример сценария для извлечения элементов массива.
/* array.e*/ /* Сценарий ProbeVue для тестирования программы на Fortran array.f */ void displayarray(int **, int, int); @@uft:$__CPID:*:displayarray:entry { int a[5][4]; /* размеры строк и столбцов меняются местами */ copy_userdata(__arg1, a); /* выводится первая строка */ printf("%d %d %d \n”, a[0][0], a[1][0], a[2][0]); /* для вывода второй строки */ printf(“%d %d %d\n", a[0][1], a[1][1], a[2][1]); } /* программа Fortran 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 . Тестировать можно все процедуры FORTRAN, перечисленные в таблице имен XCOFF. ProbeVue использует данную таблицу для получения сведений о том, где находятся указанные процедуры. Пользователь должен предоставить прототип процедуры. ProbeVue пытается получить доступ к аргументам на основе указанного прототипа. В случае использования компилятора, изменяющего имена процедур, необходимо указать измененное имя. Необходимо убедиться в том, что прототип с функциями FORTRAN соответствующим образом преобразовывается в прототип с функциями на C. См. соглашения по связыванию для передаваемых аргументов и возвращаемых значений в разделе Передача данных из одного языка в другой. Это продемонстрировано в следующем примере:
/* Программа на Fortran ext_op.f */ /* Оператор “*” перегружен для умножения рациональных чисел */ 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, вызываемый при использовании оператора “*” для умножения рациональных чисел в ext_op.f */ struct rat { int num; int den; }; struct rat rat; void __rational_arithmetic_NMOD_rat_rat(struct rat*, struct rat*,struct rat*); /* Обратите внимание, что приведено измененное имя функции. */ /* Кроме того, возвращаемая структура будет отправлена в буфер, адрес которого задан в первом аргументе. */ /* Первый явный параметр находится во втором аргументе. */ @@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; /* Адрес буфера, в котором будет храниться возвращенная структура, сохраняется при входе функции */ 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); /* Для обращения к структуре используется сохраненный адрес буфера */ printf("Return from rat_rat = %d:%d\n",rrat.num,rrat.den); exit(); } - ProbeVue не поддерживает прямое включения в сценарий заголовочных файлов Fortran. Связь между типами данных Fortran и ProbeVue можно задать в заголовочном файле ProbeVue. Этот файл можно указать с помощью опции "-I".