Provided by: manpages-fr-dev_3.65d1p1-1_all bug

NOM

       dladdr,  dlclose,  dlerror,  dlopen,  dlsym,  dlvsym  - Interface de programmation pour le
       chargeur de bibliothèques dynamiques

SYNOPSIS

       #include <dlfcn.h>

       void *dlopen(const char *filename, int flag);

       char *dlerror(void);

       void *dlsym(void *handle, const char *symbol);

       int dlclose(void *handle);

       Effectuez l'édition des liens avec l'option -ldl.

DESCRIPTION

       Les quatre fonctions dlopen(), dlsym(), dlclose(), dlerror() implémentent l'interface pour
       le chargeur de bibliothèques dynamiques.

   dlerror()
       La  fonction  dlerror()  renvoie  une  chaîne  de  caractères, compréhensible par l'homme,
       décrivant la dernière erreur survenue  dans  dlopen(),  dlsym()  ou  dlclose()  depuis  le
       dernier  appel  à  dlerror().  Elle  renvoie  NULL  si aucune erreur n'est survenue depuis
       l'initialisation ou depuis son dernier appel.

   dlopen()
       La fonction dlopen() charge la bibliothèque dynamique dont  le  nom  est  fourni  dans  la
       chaîne  filename  (terminée  par  un  caractère  nul)  et  renvoie  un  descripteur opaque
       (« handle ») représentant  la  bibliothèque  dynamique.  Si  l'argument  filename  est  un
       pointeur  NULL,  le  descripteur  renvoyé  correspond  au programme principal. Si filename
       contient une barre oblique (« / »), il est interprété comme un chemin (relatif ou absolu).
       Autrement,  le  chargeur dynamique cherche la bibliothèque de la façon suivante (consultez
       ld.so(8) pour plus de détails) :

       o   (ELF seulement) si le fichier exécutable pour le programme appelant contient la balise
           DT_RPATH mais pas la balise DT_RUNPATH, les répertoires listés dans la balise DT_RPATH
           seront parcourus.

       o   Si  à  l'instant  où  le  programme   est   démarré,   la   variable   d'environnement
           LD_LIBRARY_PATH  est  définie  et  contient  une liste de répertoires (séparés par des
           deux-points « : »), ces répertoires seront parcourus. (Par mesure de  sécurité,  cette
           variable est ignorée dans le cas de programmes set-UID et set-GID).

       o   (ELF seulement) si le fichier exécutable pour le programme appelant contient la balise
           DT_RUNPATH, les répertoires listés dans cette balise seront parcourus.

       o   Le fichier de cache /etc/ld.so.cache (maintenu par ldconfig(8)) est vérifié pour  voir
           s'il contient une entrée correspondant à filename.

       o   Les répertoires /lib et /usr/lib sont parcourus (dans cet ordre).

       Si  la  bibliothèque  a  des  dépendances  sur d'autres bibliothèques partagées, celles-ci
       seront automatiquement chargées par le chargeur dynamique, en utilisant les mêmes  règles.
       (Le  processus  peut être récursif si ces bibliothèques ont, à leur tour, des dépendances,
       et ainsi de suite.)

       L'une des deux valeurs suivantes doit être incluse dans flag :

       RTLD_LAZY
              Effectuer des liaisons paresseuses. Résoudre seulement les symboles  dont  le  code
              qui les référence est exécuté. Si le symbole n'est jamais référencé, alors il n'est
              jamais résolu. (Les bindings paresseux ne sont seulement  effectués  que  pour  les
              références  de  fonctions ; les références de variables sont toujours immédiatement
              liées quand la bibliothèque est chargée).

       RTLD_NOW
              Si cette valeur est spécifiée, ou que la variable d'environnement  LD_BIND_NOW  est
              définie  avec une chaîne non vide, tous les symboles non définis de la bibliothèque
              sont résolus avant le retour de dlopen(). Si cela ne peut pas être fait, une erreur
              est renvoyée.

       Zéro  ou  plusieurs  des valeurs suivantes peuvent être spécifiées avec un OU binaire dans
       flag :

       RTLD_GLOBAL
              Les symboles définis par cette bibliothèque seront disponibles pour  la  résolution
              des symboles des futurs chargements de bibliothèques.

       RTLD_LOCAL
              C'est  la réciproque de RTLD_GLOBAL, et le comportement par défaut si aucun drapeau
              n'est  spécifié.  Les  symboles  définis  dans  cette  bibliothèque  ne  sont   pas
              disponibles pour résoudre les références des chargements de bibliothèques futurs.

       RTLD_NODELETE (depuis la glibc 2.2)
              Ne  pas  décharger la bibliothèque lors de dlclose(). En conséquence, les variables
              statiques de la bibliothèque ne sont pas  réinitialisées  si  la  bibliothèque  est
              chargée  ultérieurement  avec  dlopen()  .  Ce  drapeau  n'est  pas  spécifié  dans
              POSIX.1-2001.

       RTLD_NOLOAD (depuis la glibc 2.2)
              Ne pas  charger  la  bibliothèque.  Ceci  peut  être  utilisé  pour  tester  si  la
              bibliothèque  n'est  pas  déjà  chargée  (dlopen()  renvoie  NULL si elle n'est pas
              chargée, ou le descripteur de la bibliothèque si elle  déjà  chargée).  Ce  drapeau
              peut  aussi  être  utilisé  pour  promouvoir  les  drapeaux d'une bibliothèque déjà
              chargée. Par exemple, une bibliothèque qui a été chargée avec RTLD_LOCAL peut  être
              de  nouveau  ouverte  avec RTLD_NOLOAD | RTLD_GLOBAL. Ce drapeau n'est pas spécifié
              dans POSIX.1-2001.

       RTLD_DEEPBIND (depuis la glibc 2.3.4)
              Placer l'espace de recherche des symboles  de  cette  bibliothèque  avant  l'espace
              global.  Cela  signifie qu'une bibliothèque autonome utilisera ses propres symboles
              de préférence aux symboles globaux de même noms  contenus  dans  les  bibliothèques
              déjà chargées. Ce drapeau n'est pas spécifié dans POSIX.1-2001.

       Si  l'argument  filename  est  un  pointeur  NULL,  le  descripteur  renvoyé correspond au
       programme principal. Lorsqu'il est passé à dlsym(), ce descripteur provoque  la  recherche
       d'un  symbole  dans  le  programme principal, puis dans toutes les bibliothèques partagées
       chargées au démarrage du programme, puis dans toutes les bibliothèques partagées  chargées
       par dlopen() avec l'attribut RTLD_GLOBAL.

       Les  références  externes  de la bibliothèque sont résolues en utilisant les bibliothèques
       mentionnées  dans  sa  liste  de  dépendances,  et   toutes   les   autres   bibliothèques
       éventuellement  ouvertes auparavant avec le drapeau RTLD_GLOBAL. Si l'édition des liens de
       l'exécutable a été faite avec  l'option  « -rdynamic »  (ou,  de  manière  synonyme,  avec
       « --export-dynamic »),  alors  les symboles globaux du programme seront également utilisés
       pour résoudre les références d'une bibliothèque chargée dynamiquement.

       Si la même bibliothèque est chargée une nouvelle fois avec dlopen(), le  même  descripteur
       sera  renvoyé.  Un compte du nombre de chargements est toutefois conservé afin d'éviter de
       la décharger avant que la fonction dlclose() n'ait été appelée autant de fois que dlopen()
       a  réussi.  La  routine  _init,  si elle existe, est appelée une seule fois. Mais un appel
       postérieur avec RTLD_NOW peut forcer la résolution  des  symboles  pour  une  bibliothèque
       précédemment chargée avec RTLD_LAZY.

       Si dlopen() échoue pour une raison quelconque, elle renvoie NULL.

   dlsym()
       La  fonction  dlsym()  prend comme arguments, un « descripteur » de bibliothèque dynamique
       renvoyé par dlopen() et un nom de  symbole  terminé  par  un  caractère  nul,  et  renvoie
       l'adresse où ce symbole a été chargé en mémoire. Si le symbole n'est pas trouvé, soit dans
       la bibliothèque spécifiée, soit dans n'importe quelle bibliothèque chargée automatiquement
       par dlopen() lorsque cette bibliothèque a été chargée, dlsym() renvoie NULL. (La recherche
       effectuée par dlsym() est d'abord en largeur à travers  l'arbre  des  dépendances  de  ces
       bibliothèques).  Le  symbole  pouvant  légitimement  avoir  la valeur NULL (la valeur NULL
       renvoyée par dlsym() n'indique  pas  nécessairement  une  erreur),  la  bonne  manière  de
       vérifier  si une erreur s'est produite est d'appeler dlerror() pour effacer toute ancienne
       condition d'erreur, puis d'appeler dlsym() et  appeler  une  nouvelle  fois  dlerror()  en
       sauvegardant  sa  valeur  de retour dans une variable et vérifier si la valeur sauvegardée
       n'est pas NULL.

       Il y a deux pseudodescripteurs spéciaux : RTLD_DEFAULT et RTLD_NEXT. Le premier  recherche
       la   première  occurrence  du  symbole  désiré  en  utilisant  l'ordre  de  recherche  des
       bibliothèques par défaut. Le second  recherche  l'occurrence  suivante  d'une  fonction  à
       partir de la bibliothèque en cours. Ceci permet de fournir une enveloppe pour une fonction
       se trouvant dans une autre bibliothèque partagée.

   dlclose()
       La fonction dlclose() décrémente le nombre de références d'une bibliothèque dynamique dont
       le  descripteur  est  handle.  Si  ce  nombre atteint zéro et si aucune autre bibliothèque
       n'emploie des symboles exportés par celle-ci, elle est déchargée.

       La fonction dlclose() renvoie 0 si elle réussit, et une valeur non nulle en cas d'erreur.

   Les symboles obsolètes _init() et _fini()
       L'éditeur de liens reconnaît les symboles spéciaux _init et  _fini.  Si  une  bibliothèque
       dynamique  exporte  une  routine  nommée  _init(),  alors  son  code  est exécuté après le
       chargement, avant le retour de dlopen(). Si la bibliothèque  exporte  une  routine  nommée
       _fini,  elle  est  appelée  juste avant le déchargement. Au cas où vous voudriez éviter de
       lier l'exécutable avec les fichiers de démarrage du  système,  vous  pouvez  spécifier  le
       paramètre -nostartfiles à la ligne de commande de gcc(1).

       L'utilisation  de  ces  routines  ou  des options gcc -nostartfiles ou -nostdlib n'est pas
       recommandée. Il peut en  résulter  un  comportement  non  désiré  tant  que  les  routines
       constructeur/destructeur  ne  sont  pas  exécutées  (à  moins que des mesures spéciales ne
       soient prises).

       À la place, les bibliothèques devraient exporter les routines en utilisant  les  fonctions
       attribut   __attribute__((constructor))   et   __attribute__((destructor)).  Consultez  la
       documentation de gcc au format Info pour plus d'information sur  celles-ci.  Les  routines
       constructeur  sont  exécutées  avant  que dlopen revienne et les routines destructeur sont
       exécutées avant que dlclose revienne.

   Extensions de la glibc :dladdr() et dlvsym()
       La glibc a ajouté deux fonctions, qui ne sont pas décrites par POSIX, dont les  prototypes
       sont :

       #define _GNU_SOURCE         /* Consultez feature_test_macros(7) */
       #include <dlfcn.h>

       int dladdr(void *addr, Dl_info *info);

       void *dlvsym(void *handle, char *symbol, char *version);

       La  fonction  dladdr() prend un pointeur vers une fonction et essaie de résoudre le nom et
       le fichier où il se trouve. L'information est stockée dans une structure Dl_info :

           typedef struct {
               const char *dli_fname; /* Chemin du fichier de l'objet partagé
                                         contenant l'adresse */
               void       *dli_fbase; /* Adresse à laquelle l'objet partagé
                                         est chargé */
               const char *dli_sname; /* Nom du symbole dont la définition
                                         chevauche addr */
               void       *dli_saddr; /* Adresse exacte du symbole dont
                                         le nom est dli_sname */
           } Dl_info;

       Si aucun symbole correspondant  à  l'adresse  addr  ne  peut  être  trouvé,  dli_sname  et
       dli_saddr sont définis à NULL.

       dladdr() renvoie 0 en cas d'erreur et une valeur non nulle en cas de succès.

       La  fonction  dlvsym(), fournie par la glibc depuis la version 2.1, effectue la même chose
       que dlsym() mais prend une version sous forme de chaîne comme argument supplémentaire.

CONFORMITÉ

       POSIX.1-2001 décrit dlclose(), dlerror(), dlopen() et dlsym().

NOTES

       Les  symboles  RTLD_DEFAULT  et  RTLD_NEXT  sont  définis  dans  <dlfcn.h>  seulement   si
       _GNU_SOURCE a été définie avant l'inclusion.

       Depuis  la  glibc 2.2.3,  atexit(3) peut être utilisée pour enregistrer un gestionnaire de
       sortie qui sera automatiquement appelé quand une bibliothèque sera déchargée.

   Historique
       L'interface standard dlopen provient de SunOS. Ce système possède également dladdr()  mais
       pas dlvsym().

BOGUES

       Quelquefois,  les  pointeurs  de  fonctions passés à dladdr() peuvent vous surprendre. Sur
       certaines architectures (notablement i386  et  x86_64),  dli_fname  et  dli_fbase  peuvent
       pointés  sur  l'objet depuis lequel vous appelez dladdr(), même si la fonction utilisée en
       paramètre semble provenir d'une bibliothèque liée dynamiquement.

       Le problème est que le pointeur de fonction ne sera résolu que  lors  de  la  compilation,
       mais  pointe  simplement  vers  la  section  de  l'objet  original plt (table de procédure
       d'édition des liens), qui redirige l'appel  après  avoir  demandé  à  l'éditeur  de  liens
       dynamique de résoudre le symbole). Un contournement consiste à compiler le code pour qu'il
       soit indépendant de son adressage : dans ce cas le compilateur ne  peut  pas  préparer  le
       pointeur  à  la  compilation,  et de nos jours, gcc(1) générera du code qui chargera juste
       l'adresse finale du  symbole  depuis  la  table  GOT  (table  d'offset  globale)  lors  de
       l'exécution, avant de la passer à dladdr().

EXEMPLE

       Charger la bibliothèque mathématique et afficher le cosinus de 2,0 :

       #include <stdio.h>
       #include <stdlib.h>
       #include <dlfcn.h>

       int
       main(int argc, char **argv)
       {
           void *handle;
           double (*cosine)(double);
           char *error;

           handle = dlopen("libm.so", RTLD_LAZY);
           if (!handle) {
               fprintf(stderr, "%s\n", dlerror());
               exit(EXIT_FAILURE);
           }

           dlerror();    /* Clear any existing error */

           cosine = (double (*)(double)) dlsym(handle, "cos");

           /* D'après le standard ISO C, la conversion de type entre un pointeur
              de fonction et « void * », comme effectuée ci-dessus, produit des
              résultats indéfinis.
              POSIX.1-2003 et POSIX.1-2008 ont admis cet état de fait et proposé
              le contournement ci-dessous :

                  *(void **) (&cosine) = dlsym(handle, "cos");

              Cette conversion (lourde) de type est conforme au standard
              ISO C and évitera tout avertissement du compilateur.

              La révision technique 2013 de POSIX.1-2008 (aussi appelée
              POSIX.1-2013) a amélioré la situation en exigeant que les
              implémentations prennent en charge la conversion du type
              « void * » vers un pointeur de fonction.'
              Cependant, certains compilateurs (par exemple gcc avec
              l'option « -pedantic ) peuvent se plaindre de la conversion
              effectuée dans ce programme. */

           error = dlerror();
           if (error != NULL) {
               fprintf(stderr, "%s\n", error);
               exit(EXIT_FAILURE);
           }

           printf("%f\n", (*cosine)(2.0));
           dlclose(handle);
           exit(EXIT_SUCCESS);
       }

       Supposons que le programme s'appelle « foo.c », on doit le compiler ainsi :

           gcc -rdynamic -o foo foo.c -ldl

       Une  bibliothèque  (bar.c  dans  l'exemple  suivant)  qui  exporte _init() et _fini() sera
       compilée comme suit :

           gcc -shared -nostartfiles -o bar bar.c

VOIR AUSSI

       ld(1), ldd(1), dl_iterate_phdr(3), rtld-audit(7), ld.so(8), ldconfig(8)

       les pages Info de ld.so, gcc, ld

COLOPHON

       Cette page fait partie de la publication 3.65 du projet man-pages Linux.  Une  description
       du  projet  et  des  instructions  pour  signaler  des  anomalies  peuvent être trouvées à
       l'adresse http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Depuis   2010,   cette   traduction   est   maintenue   à   l'aide   de    l'outil    po4a
       <http://po4a.alioth.debian.org/>  par l'équipe de traduction francophone au sein du projet
       perkamon <http://perkamon.alioth.debian.org/>.

       Christophe   Blaess   <http://www.blaess.fr/christophe/>   (1996-2003),    Alain    Portal
       <http://manpagesfr.free.fr/>  (2003-2006).  Florentin  Duneau  et  l'équipe francophone de
       traduction de Debian (2006-2009).

       Veuillez     signaler     toute     erreur     de     traduction     en     écrivant     à
       <debian-l10n-french@lists.debian.org>   ou   par   un  rapport  de  bogue  sur  le  paquet
       manpages-fr.

       Vous pouvez toujours avoir accès à la version anglaise de  ce  document  en  utilisant  la
       commande « man -L C <section> <page_de_man> ».