场景如下,需要以.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.ostrip删减符号表
生成库之后,可使用工具链中的 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链接下试试
