Man page - dlmopen(3)

Packages contains this manual

Available languages:

en fr pl ja ru

Manual

dlopen

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
dlopen()
dlmopen()
dlclose()
VALEUR RENVOYÉE
ATTRIBUTS
STANDARDS
HISTORIQUE
NOTES
dlmopen() et espace de noms
Fonctions d’initialisation et de finalisation
Historique
BOGUES
EXEMPLES
Source du programme
VOIR AUSSI
TRADUCTION

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

Image grohtml-3875589-1.png

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 .