L'homme pour gold
déclare:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
L'homme pour bfd ld
fait en quelque sorte sonner comme -rpath-link
est utilisé pour les sos inclus récursivement.
ld.lld
ne le répertorie même pas comme argument.
Quelqu'un pourrait-il clarifier cette situation pour moi?
Voici une démo, pour GNU ld
, de la différence entre -L
Et -rpath-link
- et pour faire bonne mesure, la différence entre -rpath-link
Et -rpath
.
foo.c
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
foobar.c
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
main.c
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
Créez deux bibliothèques partagées, libfoo.so
Et libbar.so
:
$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
Créez une troisième bibliothèque partagée, libfoobar.so
Qui dépend des deux premières;
$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
Oups. L'éditeur de liens ne sait pas où chercher pour résoudre -lfoo
Ou -lbar
.
L'option -L
Corrige cela.
$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
L'option -Ldir
Indique à l'éditeur de liens que dir
est l'un des répertoires pour rechercher les bibliothèques qui résolvent les options -lname
Qui lui sont données. Il recherche d'abord les répertoires -L
, Dans leur ordre de ligne de commande; puis il recherche ses répertoires par défaut configurés, dans leur ordre configuré.
Maintenant, créez un programme qui dépend de libfoobar.so
:
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
Oups encore. L'éditeur de liens détecte les dépendances dynamiques demandées par libfoobar.so
Mais ne peut pas les satisfaire. Résistons un peu à ses conseils - try using -rpath or -rpath-link
- et voyons ce que nous pouvons faire avec -L
Et -l
:
$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
Jusqu'ici tout va bien. Mais:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
au moment de l'exécution, le chargeur ne trouve pas libfoobar.so
.
Qu'en est-il alors des conseils du lieur? Avec -rpath-link
, Nous pouvons faire:
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
et ce lien réussit également.
L'option -rpath-link=dir
Indique à l'éditeur de liens que lorsqu'il rencontre un fichier d'entrée qui demande des dépendances dynamiques - comme libfoobar.so
- il doit rechercher dans le répertoire dir
pour les résoudre. Nous avons donc pas besoin pour spécifier ces dépendances avec -lfoo -lbar
Et n'avons même pas besoin de savoir ce qu'elles sont. Ce sont des informations déjà écrites dans la section dynamique de libfoobar.so
: -
$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
Nous avons juste besoin de connaître un répertoire où ils peuvent être trouvés, quels qu'ils soient.
Mais est-ce que cela nous donne un prog
exécutable?
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
Non. Identique à l'histoire comme avant. C'est parce que -rpath-link=dir
Donne à l'éditeur de liens les informations dont le chargeur aurait besoin pour résoudre certaines des dépendances dynamiques de prog
au moment de l'exécution - en supposant que cela reste vrai au moment de l'exécution - mais il n'écrit pas ces informations dans la section dynamique deprog
. Il laisse simplement le lien réussir, sans que nous ayons besoin d'énoncer toutes les dépendances dynamiques récursives du lien avec les options -l
.
Au moment de l'exécution, libfoo.so
, libbar.so
- et en fait libfoobar.so
- pourraient bien ne pas être là où ils sont maintenant - $(pwd)
- mais le chargeur pourrait être en mesure de les localiser par d'autres moyens: via le cache ldconfig
ou un paramètre de la variable d'environnement LD_LIBRARY_PATH
, par exemple:
$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir
Fournit à l'éditeur de liens les mêmes informations que rpath-link=dir
et demande à l'éditeur de liens d'insérer ces informations dans la section dynamique du fichier de sortie. Essayons cela:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
Tout bon. Parce que maintenant, prog
contient les informations dont $(pwd)
est un chemin de recherche d'exécution pour les bibliothèques partagées dont il dépend, comme nous pouvons le voir:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
Ce chemin de recherche sera essayé après les répertoires répertoriés dans LD_LIBRARY_PATH
, Le cas échéant, et avant les valeurs par défaut du système - les répertoires ldconfig
- ed, plus /lib
Et /usr/lib
.
L'option --rpath-link
Est utilisée par bfd ld pour s'ajouter au chemin de recherche utilisé pour trouver les bibliothèques partagées DT_NEEDED lors de la résolution de symboles de temps de liaison. Il s'agit essentiellement de dire à l'éditeur de liens ce qu'il faut utiliser comme chemin de recherche d'exécution lors de la tentative d'imiter ce que l'éditeur de liens dynamique ferait lors de la résolution de symboles (tel que défini par les options --rpath
Ou la variable d'environnement LD_LIBRARY_PATH
).
Gold ne suit pas les entrées DT_NEEDED lors de la résolution de symboles dans les bibliothèques partagées, donc l'option --rpath-link
Est ignorée. Il s'agissait d'une décision de conception délibérée; les dépendances indirectes n'ont pas besoin d'être présentes ou dans leurs emplacements d'exécution pendant le processus de liaison.