GCC扩展 __attribute__ ((visibility("hidden")))

  试想这样的情景,程序调用某函数A,A函数存在于两个动态链接库liba.so,libb.so中,并且程序执行需要链接这两个库,此时程序调用的A函数到底来自于a还b呢?

    这取决于链接时的顺序,比如先链接liba.so,这时候通过liba.so的导出符号表就可以找到函数A的定义,并加入到符号表中,链接libb.so的时候,符号表中已经存在函数A,就不会再更新符号表,所以调用的始终liba.so中的A函数

 

    这里的调用严重的依赖于链接库加载的顺序,可能会导致混乱;gcc的扩展中有如下属性__attribute__ ((visibility("hidden"))),可以用于抑制将一个函数的名称被导出,对连接该库的程序文件来说,该函数不可见的,使用的方法如下:

-fvisibility=default|internal|hidden|protected
gcc的visibility说,如果编译的时候用了这个属性,那么动态库的符号都hidden的,除非强制声明。
1.创建一个c源文件,内容简单

  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3.  
  4.  
  5. __attribute ((visibility("default"))) void not_hidden ()  
  6. {  
  7. printf("exported symbol\n");  
  8. }  
  9.  
  10. void is_hidden ()  
  11. {  
  12. printf("hidden one\n");  
  13. }  

先编译成一个动态库,使用到属性-fvisibility

  1. gcc -shared -o libvis.so -fvisibility=hidden vis.c 

现在查看

  1. # readelf -s libvis.so |grep hidden  
  2. 7: 0000040c 20 FUNC GLOBAL DEFAULT 11 not_hidden  
  3. 48: 00000420 20 FUNC LOCAL HIDDEN 11 is_hidden  
  4. 51: 0000040c 20 FUNC GLOBAL DEFAULT 11 not_hidden  

可以看到,属性确实有作用了。

现在试图link

  1. vi main.c  
  2. int main()  
  3. {  
  4. not_hidden();  
  5. is_hidden();  
  6. return 0;  

试图编译成一个可执行文件,链接到刚才生成的动态库,

  1. gcc -o exe main.c -L ./ -lvis 

结果提示:

  1. /tmp/cckYTHcl.o: In function `main':  
  2. main.c:(.text+0x17): undefined reference to `is_hidden'  

说明了hidden确实起到作用了。

posted on 2013-07-18 17:37  小葫芦藤  阅读(917)  评论(0编辑  收藏  举报

导航