world leader in high performance signal processing
Trace: » elf_visibility

ELF Visibility

ELF visibility allows you to control the behavior of exported symbols in your application. This page is geared more for how to actual jump in and start leveraging these features rather than going into more general details. For that information, please visit the GCC Visibility Wiki Page.

Remember that this page only applies to the FDPIC ELF binary format and not to FLAT.

Here we will be building a fictitious library named libfoo.so which comes with two files foo.c and bar.c and each file exports one function; the former exports foo while the latter exports bar.

You may also want to read the creating libraries page for details on how to create FDPIC ELF shared libraries.

Visibility Syntax (in C/C++)

There are three ways to change visibility behavior; the -fvisibility compiler flag, gcc attributes, and gcc pragmas.

There are four visibility values: default, internal, hidden, protected. Here we will focus on default and hidden. The default visibility is default of course.

To change the default visibility at compile time, just use the compiler flag -fvisibility.

$ bfin-linux-uclibc-gcc -fvisibility=hidden -c test.c -o test.o

To change the visibility of specific symbols, mark the prototype with the gcc visibility attribute in a common header. If you include the header with the marked prototypes in both the file that defines the function and the files that use the function, you only have to mark the prototype.

__attribute__((visibility("default"))) int some_exported_function(void);
__attribute__((visibility("hidden"))) int some_hidden_function(void);

Finally, you can use pragmas to control the visibility of a whole section of functions.

#pragma GCC visibility push(default)
int exported_function_one(void);
int exported_function_two(void);
int exported_function_three(void);
#pragma GCC visibility pop
 
#pragma GCC visibility push(hidden)
int hidden_function_one(void);
int hidden_function_two(void);
int hidden_function_three(void);
#pragma GCC visibility pop

Windows-Like Exporting

If you want to hide all symbols by default and be required to explicitly declare which functions are exported (this is how Windows behaves), then there are two parts.

First you should compile all of your code with the CFLAG -fvisibility=hidden:

$ bfin-linux-uclibc-gcc -fvisibility=hidden -c foo.c -o foo.o
$ bfin-linux-uclibc-gcc -fvisibility=hidden -c bar.c -o bar.o
$ bfin-linux-uclibc-gcc -shared foo.o bar.o -o libfoo.so

Then you need to mark all of the functions that you will be actually exporting with the default visibility attribute. So in a common header file:

__attribute__((visibility("default"))) int bar(void);
__attribute__((visibility("default"))) void foo(int a);

What this means is that all symbols which are not marked with the default visibility attribute will be hidden in the final shared library.

Selectively Hiding Symbols

If you'd prefer to have all symbols exported by default and just mark your internal functions as hidden, then this is a little bit simpler. You do not need any additional CFLAGS, just mark each function with a hidden visibility attribute.

__attribute__((visibility("hidden")))
int internal_foo_func(void)
{
    /* do internal foo stuff here */
}
 
void foo(int a)
{
    /* do foo stuff here */
}

Visibility Syntax (in assembly)

If you're writing assembly code, then there is just one way to control the visibility. You have to mark each symbol with one of the pseudo opcodes .hidden, .internal, or .protected. If you do not use any of these, then again the visibility is simply exported (or default).

.text
 
.global _foo
.hidden _foo
.type _foo, STT_FUNC
_foo:
    /* do foo stuff here */