记一次隐藏动态库符号的探索过程

今天遇到一个需要隐藏动态库符号的需求,记录一下。

因为某些原因需要将定制的OPENSSL库进行封装成一个新的动态库,提供给其他用户使用。并且我们用到的这个OpenSSL库是经过改造的,与系统库里自带的OpenSSL是不相同的。
先贴出Makefile

all:libsgcccrypto.a libsgcccrypto.so test
crypto.o:crypto.h crypto.h
        gcc -g -o crypto.o -fPIC -I../openssl-1-0-x/include -c crypto.c
libsgcccrypto.a:crypto.o ../openssl-1-0-x/libcrypto.a
        echo CREATE libsgcccrypto.a > ar.mac
        echo ADDLIB ../openssl-1-0-x/libcrypto.a >> ar.mac
        echo ADDMOD crypto.o >> ar.mac
        echo SAVE >> ar.mac
        echo END >> ar.mac
        ar -M < ar.mac
        rm -rf *.mac
libsgcccrypto.so:crypto.o ../openssl-1-0-x/libcrypto.a
        gcc -g -shared -fPIC -o libsgcccrypto.so crypto.o -L../openssl-1-0-x -lcrypto
test: test.c libsgcccrypto.so
        gcc -g -o test test.c -Wl,-rpath=./ -L. -lsgcccrypto -ldl
clean:
        rm -rf libsgcccrypto.a *.so *.o *.mac test


从Makefile可以看出我们的目标很简单,就是自己编写了一个crypto.c,实现了一些接口,这些接口会使用到OpenSSL里的一些功能,我们希望将新编写的crypto.c与所使用的OpenSSL库(静态库)合并编译为一个新的动态库libsgcccrypto.so。上面的Makefile可以完成这个功能。

我们来检查一下编译好的so库

[root@localhost crypto]# readelf -s libsgcccrypto.so |grep EVP| more
    91: 00000000000768cf   197 FUNC    GLOBAL DEFAULT   11 EVP_PKEY_free
   100: 00000000000e2037    13 FUNC    GLOBAL DEFAULT   11 EVP_des_ede3
   107: 00000000000e0e8c    13 FUNC    GLOBAL DEFAULT   11 EVP_des_cfb1
   108: 00000000000e397d    13 FUNC    GLOBAL DEFAULT   11 EVP_rc2_ecb
   123: 00000000000e0e99    13 FUNC    GLOBAL DEFAULT   11 EVP_des_cfb8
   430: 0000000000075faf    13 FUNC    GLOBAL DEFAULT   11 EVP_sm3
--More--

好么,OpenSSL库里的符号都导出了,可想而知,如果用户使用了我们封装的动态库,同时又使用了系统的OpenSSL库,这样一定会出问题。
首先想到的是-fvisibility=hidden选项。可惜这个选项只是在编译期间起作用,而我们的OpenSSL库是已经编译好的静态库,这个选项对已经编译好了的静态库起不了作用,但还是可以将我们crypto.c中被默认导出的一些不必要的接口隐藏掉,修改Makefile,给要导出的接口添加attribute,再看看效果。

all:libsgcccrypto.a libsgcccrypto.so test
crypto.o:crypto.h crypto.h
        gcc -g -o crypto.o -fPIC -fvisibility=hidden -I../openssl-1-0-x/include -c crypto.c
libsgcccrypto.a:crypto.o ../openssl-1-0-x/libcrypto.a
        echo CREATE libsgcccrypto.a > ar.mac
        echo ADDLIB ../openssl-1-0-x/libcrypto.a >> ar.mac
        echo ADDMOD crypto.o >> ar.mac
        echo SAVE >> ar.mac
        echo END >> ar.mac
        ar -M < ar.mac
        rm -rf *.mac
libsgcccrypto.so:crypto.o ../openssl-1-0-x/libcrypto.a
        gcc -g -shared -fPIC -o libsgcccrypto.so crypto.o -L../openssl-1-0-x -lcrypto
test: test.c libsgcccrypto.so
        gcc -g -o test test.c -Wl,-rpath=./ -L. -lsgcccrypto -ldl
clean:
        rm -rf libsgcccrypto.a *.so *.o *.mac test

/* crypto.h */
#define EXPORT_API __attribute((visibility("default")))
EXPORT_API SGCC_ENCRYPT_API sgcc_crypto_load_api();
[root@localhost crypto]# readelf -s crypto.o| grep GLOBAL |grep FUNC|more
    42: 0000000000000000    65 FUNC    GLOBAL HIDDEN    1 check_support_algs
    43: 0000000000000041    31 FUNC    GLOBAL HIDDEN    1 check_has_init
    90: 0000000000001397   167 FUNC    GLOBAL HIDDEN    1 sgcc_save_pubkey
    92: 000000000000143e   167 FUNC    GLOBAL HIDDEN    1 sgcc_save_prikey
    94: 00000000000014fa   334 FUNC    GLOBAL DEFAULT    1 sgcc_crypto_load_api

可以看到crypto.o中只有sgcc_crypto_load_api接口被导出,其他接口都是隐藏状态。这样用户连接我们的动态库就只能访问这一个接口了。

继续尝试,在链接阶段加入参数 -Wl,–exclude-libs,ALL

all:libsgcccrypto.a libsgcccrypto.so test
crypto.o:crypto.h crypto.h
        gcc -g -o crypto.o -fPIC -fvisibility=hidden -I../openssl-1-0-x/include -c crypto.c
libsgcccrypto.a:crypto.o ../openssl-1-0-x/libcrypto.a
        echo CREATE libsgcccrypto.a > ar.mac
        echo ADDLIB ../openssl-1-0-x/libcrypto.a >> ar.mac
        echo ADDMOD crypto.o >> ar.mac
        echo SAVE >> ar.mac
        echo END >> ar.mac
        ar -M < ar.mac
        rm -rf *.mac
libsgcccrypto.so:crypto.o ../openssl-1-0-x/libcrypto.a
        gcc -g -shared -fPIC -Wl,--exclude-libs,ALL -o libsgcccrypto.so crypto.o -L../openssl-1-0-x -lcrypto
test: test.c libsgcccrypto.so
        gcc -g -o test test.c -Wl,-rpath=./ -L. -lsgcccrypto -ldl
clean:
        rm -rf libsgcccrypto.a *.so *.o *.mac test
[root@localhost crypto]# readelf -s libsgcccrypto.so |grep GLOBAL|grep EVP
[root@localhost crypto]#
[root@localhost crypto]# readelf -s libsgcccrypto.so |grep GLOBAL|more
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fileno@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mktime@GLIBC_2.2.5 (2)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memset@GLIBC_2.2.5 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND ftell@GLIBC_2.2.5 (2)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close@GLIBC_2.2.5 (2)
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND ioctl@GLIBC_2.2.5 (2)
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.2.5 (2)
    11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fseek@GLIBC_2.2.5 (2)
    12: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __isoc99_sscanf@GLIBC_2.7 (3)
    13: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __assert_fail@GLIBC_2.2.5 (2)
    14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcasecmp@GLIBC_2.2.5 (2)
[root@localhost crypto]# readelf -s libsgcccrypto.so |grep GLOBAL|grep sgcc
    80: 0000000000025dc6   334 FUNC    GLOBAL DEFAULT   11 sgcc_crypto_load_api
  5669: 0000000000025dc6   334 FUNC    GLOBAL DEFAULT   11 sgcc_crypto_load_api

OK,静态库里的符号统统不见,只剩下我们需要的sgcc_crypto_load_api,这样就不怕咱们的动态库污染用户的符号空间了,目标达成!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值