我有一个这样的示例程序:
#include <stdio.h>
#if 1
#define FOR_EXPORT __attribute__ ((visibility("hidden")))
#else
#define FOR_EXPORT
#endif
FOR_EXPORT void mylocalfunction1(void)
{
printf("function1\n");
}
void mylocalfunction2(void)
{
printf("function2\n");
}
void mylocalfunction3(void)
{
printf("function3\n");
}
void printMessage(void)
{
printf("Running the function exported from the shared library\n");
}
使用
编译它gcc -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
编译结束后,我做了:
$ nm libdefaultvisibility.so
nm libdefaultvisibility.so
0000000000000eb0 t _mylocalfunction1
0000000000000ed0 t _mylocalfunction2
0000000000000ef0 t _mylocalfunction3
0000000000000f10 t _printMessage
U _printf
U dyld_stub_binder
就我所知,尽管-fvisibility=hidden
所有符号都被导出,但这意味着。我所关注的这本书声称只应导出标有FOR_EXPORT
的函数。
我看了几个其他资源,但是对于我正在进行的简单测试-fvisibility=hidden
应该足够了。
我的铿锵版:
$ clang -v
clang -v
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
答案 0 :(得分:8)
您误解了nm
的输出。滚动浏览man nm
,您就可以了
读取t
标志表示符号是本地(静态)符号
text
部分。链接器无法看到它。如果它是全球的(外部的)
标志为T
。所以你的所有四个功能都是本地的。
对比:
$ clang -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' t '
0000000000000570 t deregister_tm_clones
0000000000000600 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
0000000000000640 t frame_dummy
0000000000200e00 t __frame_dummy_init_array_entry
0000000000000670 t mylocalfunction1
0000000000000690 t mylocalfunction2
00000000000006b0 t mylocalfunction3
00000000000006d0 t printMessage
00000000000005b0 t register_tm_clones
删除-fvisibility=hidden
:
$ clang -shared -fPIC -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' t '
0000000000000600 t deregister_tm_clones
0000000000000690 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
00000000000006d0 t frame_dummy
0000000000200e00 t __frame_dummy_init_array_entry
0000000000000700 t mylocalfunction1
0000000000000640 t register_tm_clones
$ nm libdefaultvisibility.so | grep ' T '
0000000000000780 T _fini
00000000000005b0 T _init
0000000000000720 T mylocalfunction2
0000000000000740 T mylocalfunction3
0000000000000760 T printMessage
然后只有明确隐藏的mylocalfunction1
仍然是本地的,而且
其他三个现在都是全球性的。
您不应期望标有__attribute__ ((visibility("hidden")))
的符号
在任何情况下都将由共享库导出。属性意味着精确
它将不,是否明确应用于符号,如本例所示,
或者在链接器选项-fvisibility=hidden
存在的情况下默认获取。
如果您想通过visibility
归因导出示例中的那个功能
你会:
#define FOR_EXPORT __attribute__ ((visibility("default")))
然后:
$ clang -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' T '
0000000000000720 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
它是全局的,因为显式归因会覆盖命令行选项,
你所有的其他职能都是本地的。也许是令人困惑的default
可见度
总是公开。
你可以在不诉诸visibility
归属的情况下实现这一目标
不可移植 - 只需声明您不想要导出为static
的所有功能。然后是编译器
首先不会将它们暴露给链接器:
<强> foo.c的强>
#include <stdio.h>
void mylocalfunction1(void)
{
printf("function1\n");
}
static void mylocalfunction2(void)
{
printf("function2\n");
}
static void mylocalfunction3(void)
{
printf("function3\n");
}
static void printMessage(void)
{
printf("Running the function exported from the shared library\n");
}
再次获得: -
$ clang -shared -fPIC -o libfoo.so foo.c
$ nm libfoo.so | grep ' T '
00000000000006c0 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
虽然这种区别并没有在你的例子中感受到
应该理解,虽然链接器看不到本地/静态符号,并且(因此)动态链接不可用,但是全局/外部符号
可能会或可能不会可用于动态链接。 visibility
仅控制动态链接的全局符号的可用性。
答案 1 :(得分:2)
根据可见性的GCC Wiki,你应该:
在输出的DSO [动态共享对象]上使用
nm -C -D
进行前后比较 它的不同之处。
正如nm
手册中所述:
-D将显示动态符号而不是普通符号
如果我完全按照您的方式编译代码,我会得到以下对象:
$ nm -C -D libdefaultvisibility.so
nm -C -D libdefaultvisibility.so
0000000000200a68 B __bss_start
w __cxa_finalize
0000000000200a68 D _edata
0000000000200a70 B _end
00000000000006c8 T _fini
w __gmon_start__
0000000000000518 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
U puts
如果我在没有-fvisibility=hidden
选项的情况下编译它,我会得到对象:
$ nm -C -D libdefaultvisibility.so
nm -C -D libdefaultvisibility.so
0000000000200ae8 B __bss_start
w __cxa_finalize
0000000000200ae8 D _edata
0000000000200af0 B _end
0000000000000748 T _fini
w __gmon_start__
00000000000005a0 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
0000000000000712 T mylocalfunction2
0000000000000724 T mylocalfunction3
0000000000000736 T printMessage
U puts