I've tested some declaration annotation methods on a Solaris 10 machine. Surprisingly, the Solaris Studio C compiler also supports the GCC-hidden-function attribute.
A GCC configured with Solaris as
/ld
correctly implements the visibiltiy function attribute.
Thus, using the GCC function attribute syntax should be the most convenient/portable method because it works on Linux/GCC, Solaris/GCC and Solaris/Sol-Studio.
See the following table for an overview of the effects setting a function visibility to hidden.
Results
.dynsym|.symtab
System Compiler Visibility nm readelf link-error
elfdump
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Linux Fedora 17 gcc-4.7.2 not specified T GLOBAL DEFAULT no
Linux Fedora 17 gcc-4.7.2 attr-hidden t -|LOCAL DEFAULT yes
Solaris 10 gcc-4.8 not specified GLOB GLOB D no
Solaris 10 gcc-4.8 attr-hidden LOCL -|LOCL H yes
Solaris 10 cc-12.3 attr-hidden LOCL -|LOCL H yes
Solaris 10 cc-12.3 __hidden LOCL -|LOCL H yes
Methods
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "power3.h"
#include "power2.h"
int main(int argc, char **argv)
{
printf("Result: %d\n", power3(atoi(argv[1])));
// should result in a link error when symbol is hidden
printf("Result: %d\n", power2(atoi(argv[1])));
return 0;
}
power2.h:
#ifndef POWER2_H
#define POWER2_H
#if !defined(NO_HIDE)
#if defined(__GNUC__) || defined(FORCE_GCC)
__attribute__((visibility("hidden")))
#warning Using GNU-C function attribute
#elif defined(__SUNPRO_C)
__hidden
#warning Using SUNPRO-C qualifier
#endif
#endif
int
// GCC attribute also possible here
power2(int x);
#endif
power3.h:
#ifndef POWER3_H
#define POWER3_H
int power3(int x);
#endif
power3.c
#include "power3.h"
#include "power2.h"
int power3(int x)
{
return power2(x)*x;
}
Build commands:
cc -g -c -o main.o main.c
cc -g -fpic -c -o power3.po power3.c
cc -g -fpic -c -o power2.po power2.c
cc -shared -fpic -o libpower.so power3.po power2.po
cc -L$PWD -Wl,-R$PWD
Introspection:
Under Linux:
nm libpower.so | grep power
readelf --dyn-sym libpower.so | grep power
readelf -s libpower.so | grep 'FUNC.*power'
Under Solaris:
/usr/ccs/bin/nm libpower.so | grep 'FUNC.*power'
/usr/ccs/bin/elfdump -N .dynsym libpower.so | grep 'FUNC.*power'
elfdump -N .symtab libpower.so | grep 'FUNC.*power'
System details:
The Solaris 10 system is a SPARC machine and the GCC uses as
/ld
from /usr/ccs/bin
. The Solaris Studio version is 12.3 with patches applied (2013/02/04).
Sources
Global switches
For completeness, visibility of functions (and other symbols) can also be influenced by other means:
GCC-method Sol equivalent effect
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#pragma GCC visibility push(hidden) - everything between push/pop
#pragma GCC visibility pop - has default visibility hidden
#pragma GCC visibility push(default) - ~ default to default-visibility
#pragma GCC visibility pop -
-fvisibility=hidden -xldscope=hidden sets default visibility of
-fvisibility=default -xldscope=global a translation unit
The ELF standard also defines symbol visibilities internal and protected - which are also understood by the compilers, but which are less useful in general.