目标文件函数隐藏初探

 场景如下,需要以.o形式(静态库形式),发布一个库,给其他代码集成。生成库mylib.o之后,使用nm查看,可以查看到很多函数符号。但其实这个库跟外界,应该是只通过一组指定的函数接口进行交互,其他的函数不应该暴露给外界,更不应该供外界直接调用。

为此,可以进行一些处理。

将函数标记为static

一种可行的方式是,将内部使用的函数,源码中标记为static。

但这么修改之后,库本身的其他源文件,也无法使用该函数了,因为c语言中的static是将函数的作用域限定在了函数所在的源文件。

objcopy修改符号表

生成库之后,可使用工具链中的 objcopy 工具,修改符号表,将内部函数都修改为本地函数,这样外部代码无法直接链接到这些函数,只能使用指定的函数。

查看帮助可知,objcopy 支持将除 -G 参数指定的符号外,其他符号全部修改成本地符号。

objcopy --help -G --keep-global-symbol <name>   Localize all symbols except <name>

于是使用如下命令,

mv mylib.o mylib_origin.o objcopy -G api_1 -G api_2  mylib_origin.o  mylib.o

strip删减符号表

生成库之后,可使用工具链中的 strip 工具,裁剪符号表,将不打算给外界使用的函数,直接从符号表中删除。

查看帮助可知,strip可用 -s 参数删除所有符号,使用 -K 参数指定要保留的符号,使用 -N 指定要strip掉的符号。

strip --help -s --strip-all                   Remove all symbol and relocation information -N --strip-symbol=<name>         Do not copy symbol <name> -K --keep-symbol=<name>          Do not strip symbol <name>      --keep-file-symbols           Do not strip file symbol(s) 

于是使用如下命令,可删除所有符号,只保留api_1和api_2

cp mylib.o mylib_origin.o strip -s -K api_1 -K api_2 mylib.o 

使用如下命令,则是只删除inner_fun1和inner_fun2

cp mylib.o mylib_origin.o strip -N inner_fun1 -N inner_fun2 mylib.o

例子

假设库mylib.c 中有四个函数,inner_fun1,inner_fun2是内部使用的函数,api_1,api_2时给外部使用的接口。

#include <stdio.h>  void inner_fun1() { printf("inner 1\n"); } void inner_fun2() { printf("inner 2\n"); } void api_1() { printf("api 1\n"); } void api_2() { printf("api 2\n"); };

编译生产目标文件

gcc -o mylib.o -c mylib.c

查看符号表

nm mylib.o  0000000000000026 T api_1 0000000000000039 T api_2                  U _GLOBAL_OFFSET_TABLE_ 0000000000000000 T inner_fun1 0000000000000013 T inner_fun2                  U puts

四个函数都可以看到,且都是 T ,即可被外部链接。

注:对于每一个符号来说,其类型如果是小写的,则表明该符号是 local 的;大写则表明该符号是 global(external) 的。

写个main.c链接下试试


                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信