Reputation: 39195
With GCC (on Linux) I can easily limit the visibility of symbols in shared libraries.
What are my options on Solaris (10)?
Do these GCC features also work with GCC on Solaris (especially with a GCC that uses the Solaris linker/assembler)?
And does the Solaris Studio C-compiler/linker provide similar attributes/pragmas for controlling the visibility of symbols (i.e. for setting the default to hidden and explicitly marking symbols as visible)?
Upvotes: 4
Views: 2048
Reputation: 39195
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.
.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
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).
__hidden
). Section 2.9 Supported Attributes, page 40 (__visibility
).cc(1)
(__hidden
)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.
Upvotes: 4
Reputation: 39195
Another option is to use version script files. This works on Linux, Solaris/GCC and Solaris/CC.
Consider a shared library where only a function power3()
should be globally available. It uses power2()
which is defined in another translation unit and power2()
should be hidden.
Following version script specifies this:
$ cat vscript
{
global: power3;
local: *;
};
You can use one file for linking on Linux and Solaris - Linux/Solaris seem to understand the same syntactic constructs.
System Compiler Link command ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― Linux Fedora 17 gcc-4.7.2 cc -shared -Wl,--version-script,vscript -fpic -o libpower.so ... Solaris 10 gcc-4.8* gcc -shared -Wl,-M,vscript -fpic -o libpower.so ... Solaris 10 cc 12.3 cc -shared -M vscript -fpic -o libpower.so ...
Note that the GCC on Solaris is configured to use ld
/as
from /usr/ccs/bin
.
Upvotes: 3
Reputation: 94445
Can't answer about gcc visibility on Solaris, but
In the Sun Studio there are
compiler option -xldscope, and the code attributes _global/_hidden
according to http://lists.qt.nokia.com/public/qt-interest/2010-January/017893.html
http://qt.gitorious.org/qt/qt/merge_requests/433:
SunStudio since version 8 (CC version 5.5) has had the ability to control symbol visibility in ABI via the linker option
-xldscope=[global|symbolic|hidden]
and via code "attributes" __global, __symbolic & __hidden.
-xldscope=global maps to GCC's -fvisibility=default
-xldscope=symbolic maps to GCC's -fvisibility=protected
-xldscope=hidden maps to GCC's -fvisibility=hidden
__global maps to GCC's __attribute__((visibility("default"))
__symbolic maps to GCC's __attribute__((visibility("protected"))
__hidden maps to GCC's __attribute__((visibility("hidden"))
And there is an overview from Sun: http://www.oracle.com/technetwork/server-storage/solaris/symbol-scope-140496.html
Reducing Symbol Scope with Sun Studio C/C++ by Giri Mandalika, May, 2005 (revised March 22, 2006)
Upvotes: 2