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

    试想这样的情景,程序调用某函数A,A函数存在于两个动态连接库liba.so,libb.so中,而且程序执行须要连接这两个库,此时程序调用的A函数究竟是来自于a仍是b呢?sql

    这取决于连接时的顺序,好比先连接liba.so,这时候经过liba.so的导出符号表就能够找到函数A的定义,并加入到符号表中,连接libb.so的时候,符号表中已经存在函数A,就不会再更新符号表,因此调用的始终是liba.so中的A函数ide

 

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

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

   
   
            
   
   
  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
string

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



如今查看
it

   
   
            
   
   
  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
io

   
   
            
   
   
  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 


结果提示:


function

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

说明了hidden确实起到做用了。class

相关文章
相关标签/搜索