• C语言之__attribute__((visibility(“default“)))等gcc flag讲解(六十二)


    目录

    1.概述

    2.程序说明

    <1>.test.h

    <2>.test.c

    <3>.main.c

    3.编译实验

    <1>.gcc显示声明:-fvisibility=default

    <2>.gcc显示声明:-fvisibility=hidden

    <3>.gcc显示声明:-fvisibility=internal

    <4>.gcc显示声明:-fvisibility=protected


    1.概述

    -fvisibility=default / internal / hidden / protected

    上述表示:

     <1>.gcc在编译动态库的时候visibility有四个选项,只有使用default和protected选项编译时,编译出来的动态库的符号是可以被外界调用的;

     <2>.而编译时使用internal和hidden选项时,如果函数内没有:__attribute ((visibility("default")))声明,动态库使隐藏的不可被外界调用。

    2.程序说明

    <1>.test.h

    1. #include
    2. __attribute ((visibility("default"))) void test_01();
    3. void test_02();

    <2>.test.c

    1. #include "test.h"
    2. //test_01表示是"default"显示定义,说明可以被外界函数调用和导出。
    3. __attribute ((visibility("default"))) void test_01 (){
    4. printf("xxx------->%s()\n",__FUNCTION__);
    5. }
    6. //test_01表示隐士定义,如果gcc编译时,参数为-fvisibility=hidden,则不能被导出和外界调用。
    7. void test_02(){
    8. printf("xxx------->%s()\n",__FUNCTION__);
    9. }

    <3>.main.c

    1. #include "test.h"
    2. int main(){
    3. test_01();
    4. test_02();
    5. return 0;
    6. }

    3.编译实验

    <1>.gcc显示声明:-fvisibility=default

    编译动态库libtest.so: 

    # gcc -fPIC -shared -o libtest.so -fvisibility=default test.c

    查看动态库符号表状态:

    1. # readelf -s libtest.so |grep test_
    2. 6: 0000000000001142 41 FUNC GLOBAL DEFAULT 14 test_02
    3. 7: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    4. 22: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    5. 26: 0000000000001142 41 FUNC GLOBAL DEFAULT 14 test_02
    6. 注意:
    7. 可以看到test_01()和test_02()函数都是GLOBAL DEFAULT状态,说明此libtest.so可以被外界导出和调用的。

    编译main.c,并链接到libtest.so: 

    # gcc main.c -L ./ -ltest -o main

    编译无报错,说明libtest.so里的两个函数都可以被导出和调用。

    运行

    1. # export LD_LIBRARY_PATH=.
    2. # ./main
    3. xxx------->test_01()
    4. xxx------->test_02()

    <2>.gcc显示声明:-fvisibility=hidden

    编译动态库libtest.so: 

    # gcc -fPIC -shared -o libtest.so -fvisibility=hidden test.c

    查看动态库符号表状态:

    1. # readelf -s libtest.so |grep test_
    2. 6: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    3. 17: 0000000000001142 41 FUNC LOCAL DEFAULT 14 test_02
    4. 23: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    5. 注意:
    6. test_02()函数为LOCAL DEFAULT局部函数,说明不能被外界导出和调用。因为在test_02()函数没有
    7. 声明__attribute ((visibility("default"))),所以为局部隐藏,不能被外界调用。

    编译main.c,并链接到libtest.so: 

    1. # gcc main.c -L ./ -ltest -o main
    2. /usr/bin/ld: /tmp/ccD5TD6O.o: in function `main':
    3. main.c:(.text+0x18): undefined reference to `test_02'
    4. collect2: error: ld returned 1 exit status

    编译报错,说明libtest.so里的test_02()函数不可以被导出和调用。

    <3>.gcc显示声明:-fvisibility=internal

    编译动态库libtest.so: 

    # gcc -fPIC -shared -o libtest.so -fvisibility=internal test.c

    查看动态库符号表状态:

    1. # readelf -s libtest.so |grep test_
    2. 6: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    3. 17: 0000000000001142 41 FUNC LOCAL DEFAULT 14 test_02
    4. 23: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    5. 注意:
    6. test_02()函数为LOCAL DEFAULT局部函数,说明不能被外界导出和调用。因为在test_02()函数没有
    7. 声明__attribute ((visibility("default"))),所以为局部隐藏,不能被外界调用。

    编译main.c,并链接到libtest.so: 

    1. # gcc main.c -L ./ -ltest -o main
    2. /usr/bin/ld: /tmp/ccD5TD6O.o: in function `main':
    3. main.c:(.text+0x18): undefined reference to `test_02'
    4. collect2: error: ld returned 1 exit status

    编译报错,说明libtest.so里的test_02()函数不可以被导出和调用。

    <4>.gcc显示声明:-fvisibility=protected

     编译动态库libtest.so: 

    # gcc -fPIC -shared -o libtest.so -fvisibility=protected test.c

    查看动态库符号表状态:

    1. # readelf -s libtest.so |grep test_
    2. 6: 0000000000001142 41 FUNC GLOBAL DEFAULT 14 test_02
    3. 7: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    4. 22: 0000000000001119 41 FUNC GLOBAL DEFAULT 14 test_01
    5. 26: 0000000000001142 41 FUNC GLOBAL DEFAULT 14 test_02
    6. 注意:
    7. 可以看到test_01()和test_02()函数都是GLOBAL DEFAULT状态,说明此libtest.so可以被外界导出和调用的。

    编译main.c,并链接到libtest.so: 

    # gcc main.c -L ./ -ltest -o main

    编译无报错,说明libtest.so里的两个函数都可以被导出和调用。

    运行

    1. # export LD_LIBRARY_PATH=.
    2. # ./main
    3. xxx------->test_01()
    4. xxx------->test_02()

  • 相关阅读:
    2.5 自定义srv C++
    POST注入/HEAD注入
    Redis 面试题
    《公路测设技术》课程网课最新作业测验考试
    Java Number类
    Java自学网站--十几个网站的分析与评测
    FFmpeg开发笔记(三十一)使用RTMP Streamer开启APP直播推流
    HTML+CSS+JS网页设计期末课程大作业 DW个人博客网站制作 web前端开发技术 web课程设计 网页规划与设计
    C#开发mvvm模式和mvc的区别
    uniapp打包:本应用使用HBuilderX 3.8.7或对应的cli版本编译,而手机端SDK版本是3.8.12.不匹配的版本可能造成应用异常
  • 原文地址:https://blog.csdn.net/u010164190/article/details/128167936