符号可见性未按预期工作

Max*_*Max 4 c linker clang

我有一个这样的示例程序:

#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");
}
Run Code Online (Sandbox Code Playgroud)

并使用编译它

gcc -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
Run Code Online (Sandbox Code Playgroud)

现在编译完成后我做了:

$ nm libdefaultvisibility.so
nm libdefaultvisibility.so 
0000000000000eb0 t _mylocalfunction1
0000000000000ed0 t _mylocalfunction2
0000000000000ef0 t _mylocalfunction3
0000000000000f10 t _printMessage
                 U _printf
                 U dyld_stub_binder
Run Code Online (Sandbox Code Playgroud)

这意味着尽管-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
Run Code Online (Sandbox Code Playgroud)

Mik*_*han 9

你误解了输出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   
Run Code Online (Sandbox Code Playgroud)

放弃了-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
Run Code Online (Sandbox Code Playgroud)

然后只有明确隐藏的mylocalfunction1仍然是本地的,其他三个现在是全局的.

__attribute__ ((visibility("hidden"))) 在任何情况下,您都不应期望标记的符号将由共享库导出.该属性精确地表示它不会是,它是否显式应用于符号,如本例所示,或者在链接器选项存在时默认获取-fvisibility=hidden.

如果您想通过visibility属性导出示例中的那一个函数,您将拥有:

#define FOR_EXPORT __attribute__ ((visibility("default")))
Run Code Online (Sandbox Code Playgroud)

然后:

$ clang -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' T '
0000000000000720 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
Run Code Online (Sandbox Code Playgroud)

它是全局的,因为显式归因会覆盖命令行选项,而您的所有其他功能都是本地的.也许令人困惑,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");
}
Run Code Online (Sandbox Code Playgroud)

你再次获得: -

$ clang -shared -fPIC -o libfoo.so foo.c
$ nm libfoo.so | grep ' T '
00000000000006c0 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
Run Code Online (Sandbox Code Playgroud)

虽然在您的示例中没有感觉到这种区别,但您应该理解,虽然链接器看不到本地/静态符号,并且(因此)不可用于动态链接,但是全局/外部符号 可能可用或不可用于动态连锁.visibility 仅控制动态链接的全局符号的可用性.