web-dev-qa-db-fra.com

Limiter la visibilité des symboles lors de la liaison de bibliothèques partagées

Certaines plates-formes exigent que vous fournissiez une liste des symboles externes d'une bibliothèque partagée à l'éditeur de liens. Cependant, sur la plupart des systèmes unix, ce n'est pas nécessaire: tous les symboles non statiques seront disponibles par défaut.

D'après ce que je comprends, la chaîne d'outils GNU peut éventuellement limiter la visibilité aux seuls symboles explicitement déclarés. Comment peut-on y parvenir avec GNU ld?

43
rafl

GNU ld peut le faire sur les plateformes ELF.

Voici comment faire avec un script de version de l'éditeur de liens:

/* foo.c */
int foo() { return 42; }
int bar() { return foo() + 1; }
int baz() { return bar() - 1; }

gcc -fPIC -shared -o libfoo.so foo.c && nm -D libfoo.so | grep ' T '

Par défaut, tous les symboles sont exportés:

0000000000000718 T _fini
00000000000005b8 T _init
00000000000006b7 T bar
00000000000006c9 T baz
00000000000006ac T foo

Supposons que vous souhaitiez exporter uniquement les fonctions bar() et baz(). Créez un "script de version" libfoo.version:

FOO {
  global: bar; baz; # explicitly list symbols to be exported
  local: *;         # hide everything else
};

Transmettez-le à l'éditeur de liens:

gcc -fPIC -shared -o libfoo.so foo.c -Wl,--version-script=libfoo.version

Observez les symboles exportés:

nm -D libfoo.so | grep ' T '
00000000000005f7 T bar
0000000000000609 T baz
64
Employed Russian

Je pense que le moyen le plus simple de procéder consiste à ajouter le -fvisibility=hidden aux options gcc et à rendre explicitement publique la visibilité de certains symboles dans le code (par __attribute__((visibility("default")))). Voir la documentation ici .

Il y a peut-être un moyen d'y parvenir avec les scripts de l'éditeur de liens, mais je ne connais pas grand chose à ce sujet.

37
jpalecek

Le code généré pour appeler les fonctions exportées ou utiliser les éléments globaux exportés est moins efficace que ceux qui ne sont pas exportés. Il y a un niveau supplémentaire d'indirection impliqué. Ceci s’applique à toute fonction que pourrait être exporté à compiler time. gcc produira toujours une indirection supplémentaire pour une fonction qui sera ultérieurement exportée par un script de l'éditeur de liens. Donc, utiliser l'attribut de visibilité produira un meilleur code que le script de l'éditeur de liens.

5
user188731

Si vous utilisez libtool, il existe une autre option qui ressemble beaucoup à la réponse de Employed Russian.

En utilisant son exemple, ce serait quelque chose comme:

cat export.sym
bar
baz

Ensuite, lancez libtool avec l'option suivante:

libtool -export-symbols export.sym ...

Notez que lorsque vous utilisez -export-symbols, tous les symboles NE sont PAS exportés par défaut et seuls ceux de export.sym sont exportés (la ligne "local: *" de libfoo.version est donc implicite dans cette approche).

0
aaa90210