Provided by: manpages-fr-dev_4.23.1-1_all bug

NOM

       dlclose, dlopen, dlmopen - Ouvrir et fermer un objet partagé

BIBLIOTHÈQUE

       Bibliothèque de liens dynamiques (libdl, -ldl)

SYNOPSIS

       #include <dlfcn.h>

       void *dlopen(const char *filename, int flags);
       int dlclose(void *handle);

       #define _GNU_SOURCE
       #include <dlfcn.h>

       void *dlmopen(Lmid_t lmid, const char *filename, int flags);

DESCRIPTION

   dlopen()
       La  fonction  dlopen()  charge  la  bibliothèque  dynamique dont le nom est fourni dans la
       chaîne filename (terminée par l'octet NULL) et renvoie un descripteur opaque  (« handle »)
       représentant la bibliothèque dynamique. Ce descripteur est utilisé avec d'autres fonctions
       dans l'API dlopen, telles que dlsym(3), dladdr(3), dlinfo(3) et dlclose().

       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, l'éditeur dynamique de  liens  cherche  la
       bibliothèque de la façon suivante (consultez ld.so(8) pour plus de détails) :

       -  (ELF   seulement)  Si  l'objet  appelant  (c'est-à-dire  la  bibliothèque  partagée  ou
          l'exécutable depuis lequel dlopen() est appelée) contient la balise DT_RPATH  mais  pas
          la balise DT_RUNPATH, les répertoires listés dans la balise DT_RPATH seront parcourus.

       -  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-user-ID et set-group-ID.

       -  (ELF seulement) Si l'objet appelant contient  la  balise  DT_RUNPATH,  les  répertoires
          listés dans cette balise seront parcourus.

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

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

       Si l'objet indiqué dans filename a des dépendances sur d'autres objets  partagés,  ceux-ci
       seront  automatiquement  chargés  par l'éditeur dynamique de liens, en utilisant les mêmes
       règles. Le processus peut être récursif si ces objets 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. Ne résoudre les symboles que lorsque 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 liaisons paresseuses ne sont effectuées que pour les références
              de fonctions ; les références de variables sont toujours immédiatement liées  quand
              l'objet  partagé  est  chargé.  Depuis la version 2.1.1 de la glibc, ce drapeau est
              supplanté par l'effet de la variable d'environnment LD_BIND_NOW.

       RTLD_NOW
              Si cette valeur est spécifiée ou si la  variable  d'environnement  LD_BIND_NOW  est
              définie  avec une chaîne non vide, tous les symboles non définis de l'objet partagé
              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 cet  objet  partagé  seront  rendus  disponibles  pour  la
              résolution des symboles des objets partagés chargés ultérieurement.

       RTLD_LOCAL
              C'est  la  réciproque  de  RTLD_GLOBAL  et  le comportement par défaut si aucun des
              drapeaux n'est spécifié. Les symboles définis dans cet objet partagé  ne  sont  pas
              rendus  disponibles  pour  résoudre  les  références  des  objets  partagés chargés
              ultérieurement.

       RTLD_NODELETE (depuis la glibc 2.2)
              Ne pas décharger l'objet partagé lors de dlclose(). En conséquence,  les  variables
              statiques   de   l'objet   ne   sont  pas  réinitialisées  si  l'objet  est  chargé
              ultérieurement avec dlopen().

       RTLD_NOLOAD (depuis la glibc 2.2)
              Ne pas charger l'objet partagé. Cela peut  être  utilisé  pour  tester  si  l'objet
              partagé  n'est  pas déjà chargé (dlopen() renvoie NULL s'il n'est pas chargé, ou le
              descripteur de l'objet partagé s'il est déjà chargé). Ce drapeau  peut  aussi  être
              utilisé  pour  promouvoir les drapeaux d'un objet partagé déjà chargé. Par exemple,
              un objet partagé qui a été chargé avec RTLD_LOCAL peut être de nouveau ouvert  avec
              RTLD_NOLOAD | RTLD_GLOBAL.

       RTLD_DEEPBIND (depuis la glibc 2.3.4)
              Placer  l'espace  de  recherche  des  symboles  de cet objet partagé avant l'espace
              global. Cela signifie qu'un objet autonome  utilisera  de  préférence  ses  propres
              symboles aux symboles globaux de même noms contenus dans les objets déjà chargés.

       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 tous les objets partagés chargés au
       démarrage du programme, puis dans toutes les objets partagés  chargés  par  dlopen()  avec
       l'attribut RTLD_GLOBAL.

       Les références aux symboles de l'objet partagé sont résolues en utilisant (dans l'ordre) :
       les symboles dans la table de liens des objets chargés pour le programme principal et  ses
       dépendances,  les  symboles  dans  les  objets partagés (et leurs dépendances) qui ont été
       ouverts par un appel antérieur à dlopen() avec le drapeau RTLD_GLOBAL et  les  définitions
       dans  l'objet  partagé  lui-même  (ainsi  que  toute dépendance ayant été chargée pour cet
       objet).

       Tout symbole global dans l'exécutable qui a été placé dans sa table de symboles dynamiques
       par  ld(1)  peut  aussi  être  utilisé  pour résoudre les références dans un objet partagé
       dynamiquement chargé. Les symboles peuvent être placés dans la table de symbole soit parce
       que  les  liens  de l'exécutable ont été édités avec le drapeau « -rdynamic » (ou de façon
       synonyme « --export-dynamic »), qui fait que tous les  symboles  globaux  de  l'exécutable
       sont  placés  dans  la  table de symboles dynamiques, soit parce que ld(1) a identifié une
       dépendance sur un symbole dans un autre objet durant l'édition de liens statiques.

       Si le même objet partagé est chargé une nouvelle fois avec dlopen(), le  même  descripteur
       sera  renvoyé.  Un  décompte du nombre de chargements est toutefois conservé par l'éditeur
       dynamique de liens afin d'éviter de le décharger avant que la fonction dlclose() n'ait été
       appelée  autant  de  fois  que dlopen() a réussi. Les constructeurs (voir ci-dessous) sont
       seulement appelés lorsque l'objet est réellement chargé en mémoire  (c'est-à-dire  lorsque
       le compteur de références est augmenté et passe à 1).

       Un  appel  ultérieur à dlopen() qui charge le même objet partagé avec RTLD_NOW peut forcer
       la résolution de symboles pour un objet partagé chargé antérieurement avec  RTLD_LAZY.  De
       façon  similaire,  un  objet  préalablement  ouvert  avec  RTLD_LOCAL  peut  être  promu à
       RTLD_GLOBAL lors d'un appel ultérieur à dlopen().

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

   dlmopen()
       Cette fonction effectue la même tâche que dlopen() ; les arguments filename et  flags,  de
       même  que  la valeur de renvoi, sont les mêmes à l'exception des différences décrites plus
       bas.

       La fonction dlmopen() diffère de la fonction dlopen() principalement parce qu'elle accepte
       un  argument  supplémentaire, lmid, qui indique la liste de tables de liens (aussi appelée
       espace de noms) dans laquelle l'objet partagé doit être chargé. En  comparaison,  dlopen()
       ajoute  l'objet  partagé  dynamiquement  chargé au même espace de noms que l'objet partagé
       pour lequel l'appel dlopen() est fait. Le type Lmid_t est un gestionnaire opaque qui  fait
       référence à un espace de noms.

       L'argument  lmid  est  soit  l'ID  d'un  espace  de  noms existant (pouvant être obtenu en
       utilisant la requête dlinfo(3) RTLD_DI_LMID) ou l'une des valeurs spéciales suivantes :

       LM_ID_BASE
              Charger l'objet partagé dans l'espace de noms  initial  (c'est-à-dire  l'espace  de
              noms de l'application).

       LM_ID_NEWLM
              Créer  un  nouvel espace de noms et y charger l'objet partagé. Les liens de l'objet
              doivent avoir été liés pour référencer tous les autres objets partagés  dont  il  a
              besoin puisque l'espace de noms est initialement vide.

       Si filename est vide, alors l'unique valeur autorisée pour lmid est LM_ID_BASE.

   dlclose()
       La  fonction  dlclose()  décrémente  le  compteur  de références de l'objet partagé chargé
       dynamiquement et indiqué par handle.

       Si le compteur de références de cet objet tombe en dessous de  zéro  et  qu'aucun  symbole
       dans  cet  objet  n'est  requis par un autre objet, alors l'objet est déchargé après avoir
       appelé tous les destructeurs définis pour l'objet. Des symboles  dans  cet  objet  peuvent
       être requis par un autre objet parce qu'il a été ouvert avec le drapeau RTLD_GLOBAL et que
       l'un de ses symboles a permis une relocalisation dans un autre objet.

       Tous les objets partagés qui ont  été  chargés  automatiquement  lorsque  dlopen()  a  été
       invoquée sur l'objet référencé par handle sont fermés récursivement de la même façon.

       Un  renvoi  réussi  de  dlclose()  ne  garantit que les symboles associés avec handle sont
       supprimés de l'espace d'adressage de l'appelant. En plus de références résultant  d'appels
       explicites  à dlopen(), un objet partagé a peut-être été chargé de façon implicite (et les
       références prises en compte) à cause de références dans d'autres objets partagés. Ce n'est
       que lorsque toutes les références sont relachées que l'objet partagé peut être supprimé de
       l'espace d'adressage.

VALEUR RENVOYÉE

       En cas de succès, dlopen() et dlmopen() renvoient un gestionnaire  non  nul  pour  l'objet
       chargé.  En  cas  d'erreur (le fichier ne peut pas être trouvé, il n'est pas lisible, a le
       mauvais format ou bien a provoqué des erreurs  lors  de  son  chargement),  ces  fonctions
       renvoient NULL.

       En cas de succès, dlclose() renvoie 0, en cas d'erreur une valeur non nulle est renvoyée.

       Les erreurs de ces fonctions peuvent être diagnostiquées en utilisant dlerror(3).

ATTRIBUTS

       Pour une explication des termes utilisés dans cette section, consulter attributes(7).

       ┌────────────────────────────────────────────────────────┬──────────────────────┬─────────┐
       │InterfaceAttributValeur  │
       ├────────────────────────────────────────────────────────┼──────────────────────┼─────────┤
       │dlopen(), dlmopen(), dlclose()                          │ Sécurité des threads │ MT-Safe │
       └────────────────────────────────────────────────────────┴──────────────────────┴─────────┘

STANDARDS

       dlopen()
       dlclose()
              POSIX.1-2008.

       dlmopen()
       RTLD_NOLOAD
       RTLD_NODELETE
              GNU.

       RTLD_DEEPBIND
              Solaris.

HISTORIQUE

       dlopen()
       dlclose()
              glibc 2.0. POSIX.1-2001.

       dlmopen()
              glibc 2.3.4.

NOTES

   dlmopen() et espace de noms
       Une liste de table de liens définit un espace de noms isolé pour la résolution de symboles
       par l'éditeur dynamique de liens. À l'intérieur d'un espace de noms, les  objets  partagés
       dépendants  sont  implicitement  chargés  selon les règles usuelles, et les références aux
       symboles sont résolues selon les règles usuelles, mais un telle résolution est limitée aux
       définitions  fournies aux objets qui ont été chargés (explicitement et implicitement) dans
       l'espace de noms.

       La fonction dlmopen() permet une isolation de chargement d'objet, c'est-à-dire la capacité
       à  charger  un  objet  partagé  dans  un  nouvel  espace  de noms sans exposer le reste de
       l'application aux symboles rendus disponibles par le nouvel objet. Notez que l'utilisation
       du  drapeau  RTLD_LOCAL  n'est pas suffisante pour réaliser cela puisque qu'il empêche les
       symboles des objets partagés d'être disponibles à tout autre objet partagé. Dans  certains
       cas,  il  peut être souhaitable de rendre les symboles fournis par un objet partagé chargé
       dynamiquement disponibles à d'autres objets (ou à un sous-ensemble) partagés sans  exposer
       ces symboles à l'application entière. Cela peut être réalisé par l'utilisation d'un espace
       de noms séparé et du drapeau RTLD_GLOBAL.

       La fonction dlmopen() peut également être utilisée pour fournir  une  meilleure  isolation
       que  le  drapeau  RTLD_LOCAL.  En particulier, les objets partagés chargés avec RTLD_LOCAL
       peuvent être promus à RTLD_GLOBAL s'ils sont des  dépendances  d'un  autre  objet  partagé
       chargé  avec  RTLD_GLOBAL  mis  à  part  dans  le  cas  (peu commun) où l'on a un contrôle
       explicite sur les dépendances de tous les objets partagés.

       Les cas possibles d'utilisation de dlmopen() sont des greffons où l'auteur du cadriciel de
       chargement  de  greffon  ne peut pas faire confiance aux auteurs du greffon et ne souhaite
       pas que des symboles non définis du  cadriciel  greffon  soient  résolus  en  symboles  du
       greffon.  Une  autre  utilisation  est  de  charger  le  même  objet plus d'une fois. Sans
       l'utilisation de dlmopen(), cela exigerait la création de copies distinctes du fichier  de
       l'objet  partagé.  Grâce  à  l'utilisation  de  dlmopen(),  cela  peut être réalisé par le
       chargement du même fichier d'objet partagé dans différents espaces de noms.

       L'implémentation de la glibc prend en charge un nombre maximal de 16 espaces de noms.

   Fonctions d'initialisation et de finalisation
       Les objets partagés peuvent exporter des fonctions en utilisant les attributs de  fonction
       __attribute__((constructor)) et __attribute__((destructor)). Les fonctions de construction
       sont exécutées avant que dlopen()  ne  renvoie,  et  les  fonctions  de  destruction  sont
       exécutées  avant  que  dlclose()  ne  renvoie.  Un  objet  partagé peut exporter plusieurs
       constructeurs et destructeurs et des priorités peuvent être associées  à  chaque  fonction
       pour  déterminer  l'ordre dans lequel elles s'exécutent. Consultez les pages d'information
       de gcc (sous « Attributs de fonction ») pour plus d'informations.

       Une  méthode  plus  ancienne  d'obtenir  (partiellement)  le  même  résultat   passe   par
       l'utilisation  de deux symboles spéciaux reconnus par l'éditeur de liens : _init et _fini.
       Si un objet partagé chargé dynamiquement exporte une routine  nommée  _init(),  alors  son
       code  est  exécuté après le chargement d'un objet partagé, avant le retour de dlopen(). Si
       l'objet partagé exporte une  routine  nommée  _fini,  elle  est  appelée  juste  avant  le
       déchargement  de  l'objet.  Dans ce cas, vous voudrez éviter de lier l'exécutable avec les
       fichiers de démarrage  du  système,  qui  contiennent  des  versions  par  défaut  de  ces
       fichiers ;  pour cela, vous pouvez spécifier l'option -nostartfiles à la ligne de commande
       de gcc(1).

       L'utilisation de _init et _fini  est  rendue  obsolète  en  faveur  des  constructeurs  et
       destructeurs  susmentionnés,  ce  qui  entre  autres  avantages,  permet  la définition de
       plusieurs fonctions d'initialisation et de finalisation.

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

   Historique
       Ces fonctions font partie de l'API dlopen, dérivée de SunOS.

BOGUES

       Pour  la  version 2.24  de  la  glibc,  spécifier le drapeau RTLD_GLOBAL lors de l'appel à
       dlmopen() génère une erreur. De plus, spécifier RTLD_GLOBAL lors  d'un  appel  à  dlopen()
       résulte  en  un  plantage  du programme (SIGSEGV) si l'appel est effectué depuis n'importe
       quel objet chargé dans un autre espace de noms que celui initial.

EXEMPLES

       Le programme suivant charge la bibliothèque de maths (de la glibc), recherche l'adresse de
       la fonction cos(3) et affiche le cosinus de 2.0. Ci-dessous, un exemple de construction et
       d'exécution du programme :

           $ cc dlopen_demo.c -ldl
           $ ./a.out
           -0.416147

   Source du programme

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

       #include <gnu/lib-names.h>  /* Définit LIBM_SO (qui sera une
                                      chaîne telle que « libm.so.6 ») */
       int
       main(void)
       {
           void *handle;
           double (*cosine)(double);
           char *error;

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

           dlerror();    /* Supprime une erreur existante */

           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 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);
       }

VOIR AUSSI

       ld(1), ldd(1), pldd(1), dl_iterate_phdr(3), dladdr(3),  dlerror(3),  dlinfo(3),  dlsym(3),
       rtld-audit(7), ld.so(8), ldconfig(8)

       pages Info de ld, pages Info de gcc

TRADUCTION

       La  traduction  française  de  cette  page  de  manuel  a  été créée par Christophe Blaess
       <https://www.blaess.fr/christophe/>, Stéphan  Rafin  <stephan.rafin@laposte.net>,  Thierry
       Vignaud  <tvignaud@mandriva.com>,  François Micaux, Alain Portal <aportal@univ-montp2.fr>,
       Jean-Philippe   Guérard   <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)    <jean-
       luc.coulon@wanadoo.fr>,    Julien    Cristau    <jcristau@debian.org>,    Thomas   Huriaux
       <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin
       Duneau  <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis
       Barbier  <barbier@debian.org>,  David  Prévot  <david@tilapin.org>   et   Grégoire   Scano
       <gregoire.scano@malloc.fr>

       Cette  traduction  est  une  documentation libre ; veuillez vous reporter à la GNU General
       Public  License  version 3  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   concernant   les
       conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un
       message à ⟨debian-l10n-french@lists.debian.org⟩.