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

NOM

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

BIBLIOTHÈQUE

       Bibliothèque de liens dynamiques (libc, -lc)

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

Pages du manuel de Linux 6.9.1                    15 juin 2024                                         dlopen(3)