web-dev-qa-db-fra.com

Quelle est la différence entre `-rpath-link` et` -L`?

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?

13
lanza

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.

26
Mike Kinghan

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.

4
Cary Coutant