chenpengcong / blog

14 stars 3 forks source link

gcc的fvisibility选项 #2

Open chenpengcong opened 7 years ago

chenpengcong commented 7 years ago

背景:

在学习别人代码过程中发现项目编译选项添加了-fvisibility=hidden,之前自己没用过这个编译选项,因此查阅资料学习

fvisibility选项

fvisibility选项决定共享库中的符号是否是可见的。

-fvisibility=[default|internal|hidden|protected]

default意味着符号可见,hidden意味者不可见,internal和protected一般很少用

example

//foo.c
#include "stdio.h"
#include “foo.h”
int global_var = 1;

void foo()
{
    printf("foo\n");
}

//foo.h
void foo();
extern int global_var;

$ gcc -fPIC -shared foo.c -o libfoo.so $ objdump -T libfoo.so

可以看到符号表中存在foo和global_var

420892d2-c7b8-400d-8ee7-be509f51d279

加上编译选项-fvisibility=hidden

$ gcc -fPIC -shared -fvisibility=hidden foo.c -o libfoo.so $ objdump -T libfoo.so

e11aaf83-b205-4931-879d-9fa8081ac86b

可以看到符号表中不再存在foo和global_var,因此外部也就无法调用foo函数和使用全局变量global_var

PS:可以使用__attribute__ ((visibility("default")))指定符号可见性

设置不可见有什么好处

fvisibility=hidden和static有什么区别

static修饰的符号在符号表中也是不可见的,那么和fvisibility=hidden有什么区别呢

假如有一个函数用__attribute__((visibility("hidden")))修饰,那么在编译成动态共享库之后该函数是不可见的,但是如果该库由foo.o和bar.o链接而成的,那么该函数可以定义在foo.c,在bar.c中被调用,即隐藏的可见度适用于整个共享库,而不适用于组成它的单个编译单元。

而static修饰的函数只能在当前文件内被调用

参考: https://gcc.gnu.org/wiki/Visibility https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html https://stackoverflow.com/questions/17022983/is-it-possible-to-remove-symbols-from-a-shared-library-built-with-android-ndk https://stackoverflow.com/questions/14919528/what-is-the-practical-difference-between-a-static-function-and-a-function-with-t