Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symbol visibility using g++

I compiled a C++ library under Linux/Mac with its symbols hidden. I've used _attribute_ ((visibility("hidden"))) for all my classes and compiled with options (-c -O2 -fPIC -MMD -MP -MF). Under Mac, using MacDependencies (http://code.google.com/p/macdependency/), the job is done just fine as I see only my exports (I actually saw the difference before and after).

However, I noticed that using nm I still see all the names of the symbols. This happens under both Mac and Linux.

Why is that? Is there any way to avoid this?

Best Regards and thanks, Joe

like image 387
JoeSlav Avatar asked Feb 14 '11 16:02

JoeSlav


People also ask

What is visibility symbol?

A visibility property can be associated with global symbols to be used by the linker when it creates a program or a shared object. The visibility of a symbol is specified with an optional parameter of the . extern, .

What does Fvisibility hidden do?

Parts of LLVM are compiled with -fvisibility=hidden . This option forces the default visibility of all symbols to be hidden , which prevents them from being visible across library boundaries. Hiding symbols offers better control over exported symbols in a shared library.


3 Answers

Public or hidden, symbols are still there. nm shows all symbols. The difference is that hidden symbols are not available to the dynamic linker, i.e. not exported and can not be interposed.

You might also like the following man gcc:

   -fvisibility=default|internal|hidden|protected
       ...
       A good explanation of the benefits offered by ensuring ELF symbols
       have the correct visibility is given by "How To Write Shared
       Libraries" by Ulrich Drepper (which can be found at
       <http://people.redhat.com/~drepper/>)---however a superior solution
       made possible by this option to marking things hidden when the
       default is public is to make the default hidden and mark things
       public.  This is the norm with DLL's on Windows and with
       -fvisibility=hidden and "__attribute__ ((visibility("default")))"
       instead of "__declspec(dllexport)" you get almost identical
       semantics with identical syntax.  This is a great boon to those
       working with cross-platform projects.
like image 63
Maxim Egorushkin Avatar answered Sep 23 '22 15:09

Maxim Egorushkin


You can strip your binary to remove any unneeded symbols.

like image 34
Hasturkun Avatar answered Sep 24 '22 15:09

Hasturkun


On OSX (not sure about others) I found the following.

As mentioned by Maxim, using -fvisibility=hidden or __attribute__((visibility("hidden"))) still puts the symbol in the symbol table, it just gets marked as unexported. The easiest way to see this is with nm, e.g:

$ nm libfoo.dylib 
...
0000000000001fa0 t __Z10a_functionv
0000000000002140 T __Z17a_public_functionv
...

If the letter after the address is lowercase it means it isn't exported. Here a_function() is hidden, and a_public_function has default visibility.

To strip the non-exported symbols from the symbol table you can use strip -x, which according to the man page:

-x Remove all local symbols (saving only the global symbols).

$ strip -x libfoo.dylib
$ nm libfoo.dylib 
...
0000000000002140 T __Z17a_public_functionv
...

I believe (but am not 100% sure) that using hidden doesn't just amount to changing a flag, and 'unhiding' the symbols wouldn't be trivial.

like image 36
Timmmm Avatar answered Sep 26 '22 15:09

Timmmm