Développement de programmes à unités d'exécution multiples pour examiner et modifier des objets de bibliothèque pthread

La bibliothèque de débogage pthread (libpthdebug.a) fournit un ensemble de fonctions qui permettent aux développeurs d'applications d'examiner et de modifier les objets de bibliothèque pthread.

Cette bibliothèque peut être utilisée pour les applications 32 bits et 64 bits. Cette bibliothèque admet les unités d'exécution multiples. La bibliothèque de débogage pthread contient un objet partagé 32 bits et un objet partagé 64 bits.

La bibliothèque de débogage pthread permet aux applications d'accéder aux informations de la bibliothèque pthread. Cela inclut des informations sur les pthreads, les attributs pthread, les mutexes, les attributs mutex, les variables de condition, les attributs de variable de condition, les verrous en lecture / écriture, les attributs de verrou en lecture / écriture et des informations sur l'état de la bibliothèque pthread.

Remarque: toutes les données (adresses, registres) renvoyées par cette bibliothèque sont au format 64 bits pour les applications 64 bits et 32 bits. Il incombe à l'application de convertir ces valeurs au format 32 bits pour les applications 32 bits. Lors du débogage d'une application 32 bits, la moitié supérieure des adresses et des registres est ignorée.

La bibliothèque de débogage pthread ne fournit pas d'informations sur les mutex, les attributs de mutex, les variables de condition, les attributs de variable de condition, les verrous en lecture / écriture et les attributs de verrou en lecture / écriture ayant la valeur pshared de PTHREAD_PROCESS_SHARED.

Initialisation

L'application doit initialiser une session de bibliothèque de débogage pthread pour chaque processus pthreaded. La fonction pthdb_sessison_init doit être appelée à partir de chaque processus pthreadé après le chargement du processus. La bibliothèque de débogage pthread prend en charge une session pour un seul processus. L'application doit affecter un identificateur utilisateur unique et le transmettre à la fonction pthdb_session_init , qui à son tour affecte un identificateur de session unique qui doit être transmis en tant que premier paramètre à toutes les autres fonctions de la bibliothèque de débogage pthread , à l'exception de la fonction pthdb_session_pthreaded , en retour. Chaque fois que la bibliothèque de débogage pthread appelle une fonction de rappel, elle transmet à l'application l'ID utilisateur unique affecté à l'application. La fonction pthdb_session_init vérifie la liste des fonctions de rappel fournies par l'application et initialise les structures de données de la session. En outre, cette fonction définit les indicateurs de session. Une application doit transmettre l'indicateur PTHDB_FLAG_SUSPEND à la fonction pthdb_session_init . Pour obtenir la liste complète des indicateurs, voir la fonction pthdb_session_setflags .

Fonctions de rappel

La bibliothèque de débogage pthread utilise les fonctions de rappel pour obtenir et écrire des données, ainsi que pour gérer le stockage de l'application. Les fonctions de rappel requises pour une application sont les suivantes:
données_read_données
Extrait les informations sur les objets de la bibliothèque pthread
alloc
Alloue de la mémoire dans la bibliothèque de débogage pthread
réallocation
Réalloue de la mémoire dans la bibliothèque de débogage pthread
désalloc
Libère la mémoire allouée dans la bibliothèque de débogage pthread
Les fonctions de rappel facultatives pour une application sont les suivantes:
liste_regs
Nécessaire uniquement pour les sous-routines pthdb_pthread_context et pthdb_pthread_setcontext
données_écriture
Nécessaire uniquement pour la sous-routine pthdb_pthread_setcontext
write_regs
Nécessaire uniquement pour la sous-routine pthdb_pthread_setcontext

Fonction de mise à jour

Chaque fois que l'application est arrêtée, après l'initialisation de la session, il est nécessaire d'appeler la fonction pthdb_session_update . Cette fonction définit ou réinitialise les listes des pthreads, des attributs pthread, des mutex, des attributs mutex, des variables de condition, des attributs de variable de condition, des verrous en lecture / écriture, des attributs de verrou en lecture / écriture, des clés spécifiques pthread et des clés actives. Il utilise des fonctions de rappel pour gérer la mémoire des listes.

Fonctions de contexte

La fonction pthdb_pthread_context obtient les informations de contexte et la fonction pthdb_pthread_setcontext définit le contexte. La fonction pthdb_pthread_context obtient les informations de contexte d'un pthread à partir du noyau ou de la structure de données pthread dans l'espace adresse de l'application. Si pthread n'est pas associé à une unité d'exécution du noyau, les informations de contexte sauvegardées par la bibliothèque pthread sont obtenues. Si une unité d'exécution est associée à une unité d'exécution du noyau, les informations sont obtenues de l'application à l'aide des fonctions de rappel. L'application doit déterminer si l'unité d'exécution du noyau est en mode noyau ou en mode utilisateur, puis fournir les informations correctes pour ce mode.

Lorsqu'un pthread avec une unité d'exécution de noyau est en mode noyau, vous ne pouvez pas obtenir le contexte de mode utilisateur complet car le noyau ne l'enregistre pas à un seul endroit. La fonction getthrds peut être utilisée pour obtenir une partie de ces informations, car elle sauvegarde toujours la pile en mode utilisateur. L'application peut le reconnaître en vérifiant la structure thrdsinfo64.ti_scount . Si cette valeur est différente de zéro, la pile en mode utilisateur est disponible dans la structure thrdsinfo64.ti_ustk . A partir de la pile de mode utilisateur, il est possible de déterminer le registre d'adresse d'instruction (IAR) et les trames de rappel, mais pas les autres valeurs de registre. La structure thrdsinfo64 est définie dans le fichier procinfo.h .

Fonctions de liste

La bibliothèque de débogage pthread gère des listes pour les pthreads, les attributs pthread, les mutexes, les attributs mutex, les variables de condition, les attributs de variables de condition, les verrous en lecture / écriture, les attributs de verrou en lecture / écriture, les clés spécifiques pthread et les clés actives, chacune représentée par un descripteur spécifique au type. Les fonctions pthdb_objet renvoient le descripteur suivant dans la liste appropriée, où objet est l'un des suivants: pthread, attr, mutex, mutexattr, cond, condattr, rwlock, rwlockattr ou key. Si la liste est vide ou que la fin de la liste est atteinte, PTHDB_INVALID_OBJECT est signalé, où OBJECT correspond à l'un des éléments suivants: PTHREAD, ATTR, MUTEX, MUTEXATTR, COND, CONDATTR, RWLOCK, RWLOCKATTR ou KEY.

Fonctions de zone

Des informations détaillées sur un objet peuvent être obtenues à l'aide de la fonction de membre d'objet pthdb_objet_zone, où objet est l'un des suivants: pthread, attr, mutex, mutexattr, cond, condattr, rwlock, rwlockattr ou key et où field est le nom d'une zone des informations détaillées de l'objet.

Personnalisation de la session

La fonction pthdb_session_setflags permet à l'application de modifier les indicateurs qui personnalisent la session. Ces indicateurs contrôlent le nombre de registres qui sont lus ou écrits lors des opérations de contexte.

La fonction pthdb_session_flags obtient les indicateurs en cours de la session.

Arrêt de la session

A la fin de la session, les structures de données de session doivent être désallouées et les données de session doivent être supprimées. Pour ce faire, vous pouvez appeler la fonction pthdb_session_destroy , qui utilise une fonction de rappel pour libérer la mémoire. Toute la mémoire allouée par les fonctions pthdb_session_initet pthdb_session_update sera libérée.

L'exemple suivant montre comment une application peut se connecter à la bibliothèque de débogage pthread:
/* includes */

#include <thread.h>
#include <ys/pthdebug.h>

...

int my_read_data(pthdb_user_t user, pthdb_symbol_t symbols[],int count)
{
  int rc;

  rc=memcpy(buf,(void *)addr,len);                              
  if (rc==NULL) {                                               
    fprintf(stderr,&odq;Error message\n&cdq;);
    return(1);                                                  
  }                                                             
  return(0);                                                    
}
int my_alloc(pthdb_user_t user, size_t len, void **bufp)
{
  *bufp=malloc(len);                                            
  if(!*bufp) {                                                  
    fprintf(stderr,&odq;Error message\n&cdq;);
    return(1);                                                  
  }                                                             
  return(0);                                                    
}
int my_realloc(pthdb_user_t user, void *buf, size_t len, void **bufp)
{
  *bufp=realloc(buf,len);                                    
  if(!*bufp) {                                               
    fprintf(stderr,“Error message\n”);
    return(1);                                               
  }                                                          
  return(0);                                                 
}
int my_dealloc(pthdb_user_t user,void *buf)
{
  free(buf); 
  return(0); 
}

status()
{
  pthdb_callbacks_t callbacks =
                    {  NULL,                
                       my_read_data,  
                       NULL, 
                       NULL,                
                       NULL,                
                       my_alloc,            
                       my_realloc,          
                       my_dealloc,          
                       NULL                 
                    };

  ...

  rc=pthread_suspend_others_np();
  if (rc!=0)
    deal with error

  if (not initialized)
    rc=pthdb_session_init(user,exec_mode,PTHDB_SUSPEND|PTHDB_REGS,callbacks,
                          &session);
    if (rc!=PTHDB_SUCCESS)
       deal with error

  rc=pthdb_session_update(session);
  if (rc!=PTHDB_SUCCESS)
        deal with error
  
   retrieve pthread object information using the object list functions and 
   the object field functions

  ...
  
  rc=pthread_continue_others_np();
  if (rc!=0)
    deal with error
}

...

main()
{
  ...
}