gcc控制so/.dll中导出的符号

本文介绍了如何使用GCC的-fvisibility选项和__attribute__((visibility))来控制C库中的符号导出,以及versionscript作为更简洁的解决方案。通过例子展示了如何仅导出特定函数。
摘要由CSDN通过智能技术生成

传统的方法

网上的文章大多会让你使用 gcc 的 -fvisibility=hidden 来控制符号的可见性。将所有其它符号设为不可见,然后在源码中将需要导出的符号用__attribute__ ((visibility (“default”)))修饰,就可以控制要导出的符号了,参见hello.c的源码

#define DLL_PUBLIC __attribute__ ((visibility ("default")))

int call_count = 0;

DLL_PUBLIC int hello_init()
{
    call_count = 0;

    return 0;
}

int hello_call_count_add()
{
    return ++call_count;
}

DLL_PUBLIC int hello_handle()
{
    return hello_call_count_add();
}

DLL_PUBLIC void hello_exit()
{
    call_count = 0;
}

执行下列命令,显示出so文件的导出符号:

gcc -shared -fvisibility=hidden -o libhello.so hello.c
readelf --dyn-syms libhello.so

显示的导出符号如下:

Symbol table '.dynsym' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
     4: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     5: 00000000000010e9    21 FUNC    GLOBAL DEFAULT   10 hello_init
     6: 0000000000001119    16 FUNC    GLOBAL DEFAULT   10 hello_handle
     7: 0000000000001129    17 FUNC    GLOBAL DEFAULT   10 hello_exit

可以看到,没有修饰的 hello_call_count_add函数没有被导出,而修饰了的hello_init函数被导出。

使用version script控制导出符号

使用-fvisibility选项和__attribute__来控制导出符号需要大量修改源代码,有没有更简单的方法呢?有,那就是version script。

首先是没有添加任何__attribute__的hello.c源码:

int call_count = 0;

int hello_init()
{
    call_count = 0;

    return 0;
}

int hello_call_count_add()
{
    return ++call_count;
}

int hello_handle()
{
    return hello_call_count_add();
}

void hello_exit()
{
    call_count = 0;
}

建立一个简单的version-script.txt文件,内容如下:

{
    global:
        hello_init;
		hello_handle;
    
    local:
        *;
};

上述代码表示的意思是:

  • 导出hello_init,hello_handle两个符号
  • 其他符号都不导出

然后,我们在编译时,加上一个参数 -Wl,–version-script=version-script.txt,这样就可以使用 version script 来控制符号的导出了。

执行以下命令:

gcc -shared -o libhello.so hello.c -Wl,--version-script=version-script.txt
readelf --dyn-syms libhello.so

可以看到,只有hello_init,hello_handle两个符号被导出了,其余符号都没有导出

Symbol table '.dynsym' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
     4: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     5: 00000000000010e9    21 FUNC    GLOBAL DEFAULT   10 hello_init
     6: 0000000000001119    16 FUNC    GLOBAL DEFAULT   10 hello_handle
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值