linker shared-libraries gnu linker-scripts

linker - Limitar la visibilidad de los símbolos al vincular bibliotecas compartidas



shared-libraries gnu (4)

Algunas plataformas exigen que proporcione una lista de símbolos externos de una biblioteca compartida al vinculador. Sin embargo, en la mayoría de los sistemas unixish eso no es necesario: todos los símbolos no estáticos estarán disponibles por defecto.

Según tengo entendido, la cadena de herramientas de GNU puede restringir opcionalmente la visibilidad solo a símbolos explícitamente declarados. ¿Cómo se puede lograr eso usando GNU ld?


Creo que la manera más fácil de hacerlo es agregar la -fvisibility=hidden a las opciones de gcc y hacer visible de forma explícita algunos símbolos públicos en el código (por __attribute__((visibility("default"))) ). Vea la documentación here .

Puede haber una manera de lograr eso mediante los scripts del enlazador, pero no sé mucho al respecto.


El código generado para llamar a cualquier función exportada o usar cualquier elemento global exportado es menos eficiente que aquellos que no se exportan. Hay un nivel extra de indirección involucrado. Esto se aplica a cualquier función que pueda exportarse en tiempo de compilación . gcc aún producirá una indirección adicional para una función que luego no será exportada por un script del enlazador. Entonces, usar el atributo de visibilidad producirá un mejor código que el script del enlazador.


Si está utilizando libtool, hay otra opción muy similar a la respuesta del ruso empleado.

Usando su ejemplo, sería algo así como:

cat export.sym bar baz

A continuación, ejecute libtool con la siguiente opción:

libtool -export-symbols export.sym ...

Tenga en cuenta que al usar -export-symbols, todos los símbolos NO se exportan por defecto, y solo aquellos en export.sym se exportan (por lo que la línea "local: *" en libfoo.version está implícita en este enfoque).


GNU ld puede hacer eso en plataformas ELF.

Aquí es cómo hacerlo con una secuencia de comandos de versión del enlazador:

/* 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 ''

Por defecto, todos los símbolos se exportan:

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

Digamos que quiere exportar solo bar() y baz() . Cree un "script de versión" libfoo.version :

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

Pásalo al enlazador:

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

Observe los símbolos exportados:

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