Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limiting visibility of symbols when linking shared libraries

Some platforms mandate that you provide a list of a shared library's external symbols to the linker. However, on most unixish systems that's not necessary: all non-static symbols will be available by default.

My understanding is that the GNU toolchain can optionally restrict visibility just to symbols explicitly declared. How can that be achieved using GNU ld?

like image 877
rafl Avatar asked Jan 12 '09 13:01

rafl


People also ask

What is visibility symbol?

What is symbol and symbol visibility. Symbol is one of the basic terms when talking about object files, linking, and so on. In fact, in C/C++ language, symbol is the corresponding entity of most user-defined variables, function names, mangled with namespace, class/struct/name, and so on.

Do static libraries have symbols?

At link time, a static library can have unresolved symbols in it, as long as you don't need the unresolved symbols, and you don't need any symbol that is in a .o file that contains an unresolved symbol.

How shared library are linked?

Shared libraries (also called dynamic libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables and the like) required by the program, are either linked into the program, or in one of its shared libraries.

What is a shared library used for?

Shared libraries allow a single instance of some pre-compiled code to be shared between several programs. In contrast, with static linking the code is copied into each program. Using shared libraries can thus save disk space.


1 Answers

GNU ld can do that on ELF platforms.

Here is how to do it with a linker version script:

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

By default, all symbols are exported:

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

Let's say you want to export only bar() and baz(). Create a "version script" libfoo.version:

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

Pass it to the linker:

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

Observe exported symbols:

nm -D libfoo.so | grep ' T ' 00000000000005f7 T bar 0000000000000609 T baz 
like image 92
Employed Russian Avatar answered Sep 21 '22 04:09

Employed Russian