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


Algunas plataformas exigen que proporcione una lista de los símbolos externos de una biblioteca compartida al enlazador. 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.

Entiendo que la cadena de herramientas GNU puede restringir opcionalmente la visibilidad solo a los símbolos declarados explícitamente. ¿Cómo se puede lograr esto usando GNU ld?

Author: Die in Sente, 2009-01-12

4 answers

GNU ld puede hacer eso en plataformas ELF.

Aquí está cómo hacerlo con un script de versión 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 desea exportar solo bar() y baz(). Crear 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
 61
Author: Employed Russian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-17 07:51:03

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

Puede haber una manera de lograr eso mediante scripts enlazadores ld, pero no se mucho al respecto.

 35
Author: jpalecek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-26 00:57:39

El código generado para llamar a cualquier función exportada o usar cualquier global exportado es menos eficiente que aquellos que no se exportan. Hay un nivel extra de indirección involucrada. Esto se aplica a cualquier función que pueda exportarse a la hora de compilar . gcc seguirá produciendo indirectas adicionales para una función que posteriormente se des-exporta mediante un script enlazador. Por lo tanto, el uso del atributo visibility producirá un código mejor que el script enlazador.

 5
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-12 23:04:51

Si está utilizando libtool, hay otra opción muy parecida a la respuesta de Employed Russian.

Usando su ejemplo, sería algo como:

cat export.sym
bar
baz

Luego ejecute libtool con la siguiente opción:

libtool -export-symbols export.sym ...

Tenga en cuenta que cuando se usa-export-symbols todos los símbolos NO se exportan por defecto, y solo los que están en export.sym se exportan (por lo que la línea" local: * " en libfoo.versión es en realidad implícita en este enfoque).

 0
Author: aaa90210,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-27 22:14:15