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> ».

Linux                                            8 janvier 2014                                        DLOPEN(3)