Où les exécutables recherchent-ils des objets partagés au moment de l'exécution?

102

Je comprends comment définir des objets partagés au moment de la liaison / compilation. Cependant, je me demande toujours comment les exécutables recherchent l’objet partagé ( *.sobibliothèques) au moment de l’exécution.

Par exemple, mon application a.outappelle des fonctions définies dans la lib.sobibliothèque. Après la compilation, je passe lib.soà un nouveau répertoire dans mon répertoire $HOME.

Comment puis-je dire a.outd'aller chercher là-bas?

Rahmu
la source

Réponses:

102

Le HOWTO sur les bibliothèques partagées explique la plupart des mécanismes impliqués et le manuel du chargeur dynamique donne plus de détails. Chaque variante unix a sa propre manière, mais la plupart utilisent le même format exécutable ( ELF ) et ont des lieurs dynamiques similaires (dérivés de Solaris). Ci-dessous, je vais résumer le comportement courant en mettant l’accent sur Linux. Consultez les manuels de votre système pour connaître l'histoire complète.

En résumé, lorsqu'il recherche une bibliothèque dynamique ( .sofichier), l'éditeur de liens essaie:

  • répertoires répertoriés dans la LD_LIBRARY_PATHvariable d'environnement ( DYLD_LIBRARY_PATHsous OSX);
  • répertoires listés dans le rpath de l'exécutable ;
  • les répertoires du chemin de recherche du système, qui (sous Linux au minimum) sont composés des entrées dans /etc/ld.so.confplus /libet /usr/lib.

Le rpath est stocké dans l'exécutable (c'est l' attribut DT_RPATHou DT_RUNPATHdynamic). Il peut contenir des chemins absolus ou des chemins commençant par $ORIGINpour indiquer un chemin relatif à l'emplacement de l'exécutable (par exemple, si l'exécutable est in /opt/myapp/binet que son chemin d'accès est $ORIGIN/../lib:$ORIGIN/../pluginsalors, l'éditeur de liens dynamique recherchera dans /opt/myapp/libet /opt/myapp/plugins). Le rpath est normalement déterminé lors de la compilation de l'exécutable, avec l' -rpathoption to ld, mais vous pouvez le changer par la suite avec chrpath.

Dans le scénario que vous décrivez, si vous êtes le développeur ou emballeur de l'application et l' intention qu'il soit installé dans une …/bin, la …/libstructure, puis liaison avec -rpath='$ORIGIN/../lib'. Si vous installez un fichier binaire pré-construit sur votre système, placez la bibliothèque dans un répertoire du chemin de recherche ( /usr/local/libsi vous êtes l'administrateur système, sinon un répertoire auquel vous vous ajoutez $LD_LIBRARY_PATH), ou essayez chrpath.

Gilles
la source
3
Sur certains systèmes, /lib64et /usr/lib64sont utilisés pour des binaires 64 bits et /libet /usr/libsont utilisés pour binaires 32 bits.
Mark Lakata
Pourquoi cette bonne réponse ne parle- t-elle pas de ldconfig ?
Loves Probability
1
@LovesProbability Parce que la question portait sur l'endroit où les exécutables recherchent des bibliothèques, ce qui n'implique pas ldconfig. ldconfigs'implique lorsque vous installez une bibliothèque.
Gilles
1
Notez que le "chemin de recherche du système" pour les *.sobibliothèques n’est pas le même que $PATH. Le chemin de recherche est tel que donné par @enzotib dans leur réponse. Pour imprimer les chemins qui seront recherchés, lancez ldconfig -v 2>/dev/null | grep -v ^$'\t'.
Andrew Bate
pour moi, pour lancer ldconfig, il me fallait /sbin/ldconfiget cette autre magie d’Andrew Bate pour le faire tourner non-root
Robert Lugg
16

Sous Linux, le comportement est expliqué dans la ld(1)page de manuel

       The linker uses the following search paths to locate required
       shared libraries:

       1.  Any directories specified by -rpath-link options.

       2.  Any directories specified by -rpath options.  The difference
           between -rpath and -rpath-link is that directories specified by
           -rpath options are included in the executable and used at
           runtime, whereas the -rpath-link option is only effective at
           link time. Searching -rpath in this way is only supported by
           native linkers and cross linkers which have been configured
           with the --with-sysroot option.

       3.  On an ELF system, for native linkers, if the -rpath and
           -rpath-link options were not used, search the contents of the
           environment variable "LD_RUN_PATH".

       4.  On SunOS, if the -rpath option was not used, search any
           directories specified using -L options.

       5.  For a native linker, the search the contents of the environment
           variable "LD_LIBRARY_PATH".

       6.  For a native ELF linker, the directories in "DT_RUNPATH" or
           "DT_RPATH" of a shared library are searched for shared
           libraries needed by it. The "DT_RPATH" entries are ignored if
           "DT_RUNPATH" entries exist.

       7.  The default directories, normally /lib and /usr/lib.

       8.  For a native linker on an ELF system, if the file
           /etc/ld.so.conf exists, the list of directories found in that
           file.

       If the required shared library is not found, the linker will issue
       a warning and continue with the link.
enzotib
la source
1
"Les répertoires par défaut, normalement / lib et / usr / lib." -> comment puis-je savoir si mon système est normal?
Thorsten Staerk
2
La question concerne le temps d'exécution et non le temps de liaison
Talespin_Kit
2

Je suis à peu près sûr que la réponse est ici ldconfig.

ldconfig crée les liens nécessaires et met en cache les dernières bibliothèques partagées trouvées dans les répertoires spécifiés sur la ligne de commande, dans le fichier /etc/ld.so.conf et dans les répertoires de confiance (/ lib et / usr / lib). Le cache est utilisé par l'éditeur de liens au moment de l'exécution, ld.so ou ld-linux.so. ldconfig vérifie l'en-tête et les noms de fichiers des bibliothèques rencontrées lors de la détermination des versions dont les liens doivent être mis à jour.

http://linux.die.net/man/8/ldconfig

Sean C.
la source
0

Pour les applications en cours d'exécution, le fichier /proc/1234/mapscontient toutes les bibliothèques liées dynamiquement.

1234est le pid de l'exécutable en cours d'exécution.

Linux suit LD_LIBRARY_PATH et d’autres variables, comme indiqué dans la réponse de Gilles.

utilisateur138692
la source
4
C'est bien que vous confirmiez dans votre deuxième phrase que la réponse de Gilles aide. La première partie ne contribue cependant pas du tout à expliquer comment indiquer à un fichier où se trouvent les fichiers, mais seulement où ils ont été obtenus s'ils ont déjà été trouvés. Dans l'ensemble, cela ne devrait être qu'un commentaire, pas une réponse.
Anthon