Provided by:
manpages-fr-dev_3.27fr1.4-1_all 
NOM
dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym - Interface de
programmation pour le chargeur de bibliotheques 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'edition des liens avec l'option -ldl.
DESCRIPTION
Les quatre fonctions dlopen(), dlsym(), dlclose(), dlerror()
implementent l'interface pour le chargeur de bibliotheques dynamiques.
dlerror()
La fonction dlerror() renvoie une chaine de caracteres, comprehensible
par l'homme, decrivant la derniere erreur survenue dans dlopen(),
dlsym() ou dlclose() depuis le dernier appel a dlerror(). Elle renvoie
NULL si aucune erreur n'est survenue depuis l'initialisation ou depuis
son dernier appel.
dlopen()
La fonction dlopen() charge la bibliotheque dynamique dont le nom est
fourni dans la chaine filename (terminee par un caractere nul) et
renvoie un descripteur opaque (<< handle >>) representant la
bibliotheque dynamique. Si l'argument filename est un pointeur NULL, le
descripteur renvoye correspond au programme principal. Si filename
contient une barre oblique (<< / >>), il est interprete comme un chemin
(relatif ou absolu). Autrement, le chargeur dynamique cherche la
bibliotheque de la facon suivante (consultez ld.so(8) pour plus de
details) :
o (ELF seulement) si le fichier executable pour le programme appelant
contient la balise DT_RPATH mais pas la balise DT_RUNPATH, les
repertoires listes dans la balise DT_RPATH seront parcourus.
o Si a l'instant ou le programme est demarre, la variable
d'environnement LD_LIBRARY_PATH est definie et contient une liste
de repertoires (separes par des deux-points << : >>), ces
repertoires seront parcourus. (Par mesure de securite, cette
variable est ignoree dans le cas de programmes set-UID et set-GID).
o (ELF seulement) si le fichier executable pour le programme appelant
contient la balise DT_RUNPATH, les repertoires listes dans cette
balise seront parcourus.
o Le fichier de cache /etc/ld.so.cache (maintenu par ldconfig(8)) est
verifie pour voir s'il contient une entree correspondant a
filename.
o Les repertoires /lib et /usr/lib sont parcourus (dans cet ordre).
Si la bibliotheque a des dependances sur d'autres bibliotheques
partagees, celles-ci seront automatiquement chargees par le chargeur
dynamique, en utilisant les memes regles. (Le processus peut etre
recursif si ces bibliotheques ont, a leur tour, des dependances, et
ainsi de suite.)
L'une des deux valeurs suivantes doit etre incluse dans flag :
RTLD_LAZY
Effectuer des liaisons paresseuses. Resoudre seulement les
symboles dont le code qui les reference est execute. Si le
symbole n'est jamais reference, alors il n'est jamais resolu.
(Les bindings paresseux ne sont seulement effectues que pour les
references de fonctions ; les references de variables sont
toujours immediatement liees quand la bibliotheque est chargee).
RTLD_NOW
Si cette valeur est specifiee, ou que la variable
d'environnement LD_BIND_NOW est definie avec une chaine non
vide, tous les symboles non definis de la bibliotheque sont
resolus avant le retour de dlopen(). Si cela ne peut pas etre
fait, une erreur est renvoyee.
Zero ou plusieurs des valeurs suivantes peuvent etre specifiees avec un
OU binaire dans flag :
RTLD_GLOBAL
Les symboles definis par cette bibliotheque seront disponibles
pour la resolution des symboles des futurs chargements de
bibliotheques.
RTLD_LOCAL
C'est la reciproque de RTLD_GLOBAL, et le comportement par
defaut si aucun drapeau n'est specifie. Les symboles definis
dans cette bibliotheque ne sont pas disponibles pour resoudre
les references des chargements de bibliotheques futurs.
RTLD_NODELETE (depuis la glibc 2.2)
Ne pas decharger la bibliotheque lors de dlclose(). En
consequence, les variables statiques de la bibliotheque ne sont
pas reinitialisees si la bibliotheque est chargee ulterieurement
avec dlopen() . Ce drapeau n'est pas specifie dans POSIX.1-2001.
RTLD_NOLOAD (depuis la glibc 2.2)
Ne pas charger la bibliotheque. Ceci peut etre utilise pour
tester si la bibliotheque n'est pas deja chargee (dlopen()
renvoie NULL si elle n'est pas chargee, ou le descripteur de la
bibliotheque si elle deja chargee). Ce drapeau peut aussi etre
utilise pour promouvoir les drapeaux d'une bibliotheque deja
chargee. Par exemple, une bibliotheque qui a ete chargee avec
RTLD_LOCAL peut etre de nouveau ouverte avec
RTLD_NOLOAD | RTLD_GLOBAL. Ce drapeau n'est pas specifie dans
POSIX.1-2001.
RTLD_DEEPBIND (depuis la glibc 2.3.4)
Placer l'espace de recherche des symboles de cette bibliotheque
avant l'espace global. Cela signifie qu'une bibliotheque
autonome utilisera ses propres symboles de preference aux
symboles globaux de meme noms contenus dans les bibliotheques
deja chargees. Ce drapeau n'est pas specifie dans POSIX.1-2001.
Si l'argument filename est un pointeur NULL, le descripteur renvoye
correspond au programme principal. Lorsqu'il est passe a dlsym(), ce
descripteur provoque la recherche d'un symbole dans le programme
principal, puis dans toutes les bibliotheques partagees chargees au
demarrage du programme, puis dans toutes les bibliotheques partagees
chargees par dlopen() avec l'attribut RTLD_GLOBAL.
Les references externes de la bibliotheque sont resolues en utilisant
les bibliotheques mentionnees dans sa liste de dependances, et toutes
les autres bibliotheques eventuellement ouvertes auparavant avec le
drapeau RTLD_GLOBAL. Si l'edition des liens de l'executable a ete faite
avec l'option << -rdynamic >> (ou, de maniere synonyme, avec
<< --export-dynamic >>), alors les symboles globaux du programme seront
egalement utilises pour resoudre les references d'une bibliotheque
chargee dynamiquement.
Si la meme bibliotheque est chargee une nouvelle fois avec dlopen(), le
meme descripteur sera renvoye. Un compte du nombre de chargements est
toutefois conserve afin d'eviter de la decharger avant que la fonction
dlclose() n'ait ete appelee autant de fois que dlopen() a reussi. La
routine _init, si elle existe, est appelee une seule fois. Mais un
appel posterieur avec RTLD_NOW peut forcer la resolution des symboles
pour une bibliotheque precedemment chargee avec RTLD_LAZY.
Si dlopen() echoue pour une raison quelconque, elle renvoie NULL.
dlsym()
La fonction dlsym() prend comme arguments, un << descripteur >> de
bibliotheque dynamique renvoye par dlopen() et un nom de symbole
termine par un caractere nul, et renvoie l'adresse ou ce symbole a ete
charge en memoire. Si le symbole n'est pas trouve, soit dans la
bibliotheque specifiee, soit dans n'importe quelle bibliotheque chargee
automatiquement par dlopen() lorsque cette bibliotheque a ete chargee,
dlsym() renvoie NULL. (La recherche effectuee par dlsym() est d'abord
en largeur a travers l'arbre des dependances de ces bibliotheques). Le
symbole pouvant legitimement avoir la valeur NULL (la valeur NULL
renvoyee par dlsym() n'indique pas necessairement une erreur), la bonne
maniere de verifier 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 verifier si la
valeur sauvegardee n'est pas NULL.
Il y a deux pseudo-descripteurs speciaux : RTLD_DEFAULT et RTLD_NEXT.
Le premier recherche la premiere occurrence du symbole desire en
utilisant l'ordre de recherche des bibliotheques par defaut. Le second
recherche l'occurrence suivante d'une fonction a partir de la
bibliotheque en cours. Ceci permet de fournir une enveloppe pour une
fonction se trouvant dans une autre bibliotheque partagee.
dlclose()
La fonction dlclose() decremente le nombre de references d'une
bibliotheque dynamique dont le descripteur est handle. Si ce nombre
atteint zero et si aucune autre bibliotheque n'emploie des symboles
exportes par celle-ci, elle est dechargee.
La fonction dlclose() renvoie 0 si elle reussit, et une valeur non
nulle en cas d'erreur.
Les symboles obsol`etes _init() et _fini()
L'editeur de liens reconnait les symboles speciaux _init et _fini. Si
une bibliotheque dynamique exporte une routine nommee _init(), alors
son code est execute apres le chargement, avant le retour de dlopen().
Si la bibliotheque exporte une routine nommee _fini, elle est appelee
juste avant le dechargement. Au cas ou vous voudriez eviter de lier
l'executable avec les fichiers de demarrage du systeme, vous pouvez
specifier le parametre -nostartfiles a la ligne de commande de gcc(1).
L'utilisation de ces routines ou des options gcc -nostartfiles ou
-nostdlib n'est pas recommandee. Il peut en resulter un comportement
non desire tant que les routines constructeur/destructeur ne sont pas
executees (a moins que des mesures speciales ne soient prises).
A la place, les bibliotheques 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 executees avant que dlopen revienne et les routines
destructeur sont executees avant que dlclose revienne.
Extensions de la glibc :dladdr() et dlvsym()
La glibc a ajoute deux fonctions, qui ne sont pas decrites par POSIX,
dont les prototypes sont :
#define _GNU_SOURCE
#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
resoudre le nom et le fichier ou il se trouve. L'information est
stockee dans une structure Dl_info :
typedef struct {
const char *dli_fname; /* Chemin du fichier de l'objet partage
contenant l'adresse */
void *dli_fbase; /* Adresse a laquelle l'objet partage
est charge */
const char *dli_sname; /* Nom du symbole le plus proche avec
une adresse inferieure a addr */
void *dli_saddr; /* Adresse exacte du symbole dont
le nom est dli_sname */
} Dl_info;
Si aucun symbole correspondant a l'adresse addr ne peut etre trouve,
dli_sname et dli_saddr sont definis a NULL.
dladdr() renvoie 0 en cas d'erreur et une valeur non nulle en cas de
succes.
La fonction dlvsym(), fournie par la glibc depuis la version 2.1,
effectue la meme chose que dlsym() mais prend une version sous forme de
chaine comme argument supplementaire.
CONFORMIT'E
POSIX.1-2001 decrit dlclose(), dlerror(), dlopen() et dlsym().
NOTES
Les symboles RTLD_DEFAULT et RTLD_NEXT sont definis dans <dlfcn.h>
seulement si _GNU_SOURCE a ete definie avant l'inclusion.
Depuis la glibc 2.2.3, atexit(3) peut etre utilisee pour enregistrer un
gestionnaire de sortie qui sera automatiquement appele quand une
bibliotheque sera dechargee.
Historique
L'interface standard dlopen provient de SunOS. Ce systeme possede
egalement dladdr() mais pas dlvsym().
BOGUES
Quelquefois, les pointeurs de fonctions passes a dladdr() peuvent vous
surprendre. Sur certaines architectures (notablement i386 et x86_64),
dli_fname et dli_fbase peuvent pointes sur l'objet depuis lequel vous
appelez dladdr(), meme si la fonction utilisee en parametre semble
provenir d'une bibliotheque liee dynamiquement.
Le probleme est que le pointeur de fonction ne sera resolu que lors de
la compilation, mais pointe simplement vers la section de l'objet
original plt (table de procedure d'edition des liens), qui redirige
l'appel apres avoir demande a l'editeur de liens dynamique de resoudre
le symbole). Un contournement consiste a compiler le code pour qu'il
soit independant de son adressage : dans ce cas le compilateur ne peut
pas preparer le pointeur a la compilation, et de nos jours, gcc(1)
generera du code qui chargera juste l'adresse finale du symbole depuis
la table GOT (table d'offset globale) lors de l'execution, avant de la
passer a dladdr().
EXEMPLE
Charger la bibliotheque mathematique 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 */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != 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 bibliotheque (bar.c dans l'exemple suivant) qui exporte _init() et
_fini() sera compilee comme suit :
gcc -shared -nostartfiles -o bar bar.c
VOIR AUSSI
ld(1), ldd(1), dl_iterate_phdr(3), feature_test_macros(7),
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.27 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent etre trouvees a l'adresse
<URL:http://www.kernel.org/doc/man-pages/>.
TRADUCTION
Depuis 2010, cette traduction est maintenue a l'aide de l'outil po4a
<URL:http://po4a.alioth.debian.org/> par l'equipe de traduction
francophone au sein du projet perkamon
<URL:http://perkamon.alioth.debian.org/>.
Christophe Blaess <URL:http://www.blaess.fr/christophe/> (1996-2003),
Alain Portal <URL:http://manpagesfr.free.fr/> (2003-2006). Florentin
Duneau et l'equipe francophone de traduction de Debian (2006-2009).
Veuillez signaler toute erreur de traduction en ecrivant a
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir acces a la version anglaise de ce document
en utilisant la commande << man -L C <section> <page_de_man> >>.
Linux 6 decembre 2008 DLOPEN(3)