I want to hide symbol names which are not relevant to the last user and make visible only APIs in my shared or static library. I have a simple code like that:
I realize this is already an old thread. However, I'd like to share some facts about static linking in the sense of making hidden symbols local and hence prevent those symbols from (global) static linkage in an object file or static library. This does not mean making them invisible in the symbol table.
Mike Kingham's answer is very usefull but not complete on the following detail:
If you want to conceal f_b1 and f_b3 from static linkage in a static library, you cannot use the visibility attribute to do that at all.
Let me show that hidden symbols can certainly be made local by using the example of the simple code in file.c and applying ypsu's answer in Symbol hiding in static libraries built with Xcode/gcc.
At a first step let's reproduce the objdump output with the hidden attribute visible on f_b1 and f_b3. This can be done by the following command, which gives all functions in file.c the hidden attribute:
gcc -fvisibility=hidden -c file.c
Output of objdump -t file.o gives
file.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 file.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g F .text 000000000000000b .hidden f_b1
000000000000000b g F .text 0000000000000010 .hidden f_b3
This is exactly the same intermediate result as obtained by Mike Kingham. Now let's make the symbols with the hidden attribute local. That is accomplished by using objcopy from binutils as follows:
objcopy --localize-hidden --strip-unneeded file.o
Using objdump, gives
file.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l F .text 000000000000000b .hidden f_b1
000000000000000b l F .text 0000000000000010 .hidden f_b3
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
Likewise, nm file.o gives
0000000000000000 t f_b1
000000000000000b t f_b3
Although f_b1 and f_b3 are still visible in the the symbol table they are local. Hence, functions f_b1 and f_b3 are concealed from static linking!
I'd also like to add a note on declaring functions static and by that having the possibility to remove them from the symbol table completely. First, the removal can be done deterministically and not depending on compiler optimization by using objcopy.
objcopy --strip-unneeded file.o
The static functions f_b1 and f_b2 are not anymore in the symbol table of file.o.
Secondly, this use of declaring functions static to let them disappear from the symbol table only works in single source file C-projects. As soon as a C-project consists of many components and hence files this only can be done by merging all C-source and -header files into one single source file and declare all internal interfaces (functions) static with obvious the exception of the global (top) interface. If that is not possible, one can fallback to the method originally described by ypsu (and probably many others - see for instance Restricting symbols in a Linux static library).