生成库的时候,只想暴露接口符号给调用者,其他的符号需要删除,怎么办?
方法1
#hidden符号增加local flag
objcopy --strip-uneeded --localize-hidden libxxx.a
#设置所有符号为local(可能有副作用)
objcopy -G not_exist_sym libxxx.a
#根据need_globals_symbols_list.txt,将其中所有符号设置为global
objcopy --globalize-symbols=need_globals_symbols_list.txt libxxx.a
#移除local符号
strip -x libxxx.a
#移除其他非local符号
strip -N sym_name libxxx.a
#只保留某些符号
strip -s -K sym_name libxxx.a
#轻度混淆,重命名section和无法strip的symbol
objcopy --redefine-sym old_sym=new_sym libxxx.a
objcopy --rename-section old_sect=new_sect libxxx.a
这个方法适合没有源码的情况,缺点有:
1.原始库需要被删除的符号必须是hidden (即编译时参数 -fvisibility=hidden 或手动指定 __attribute((visibility("hidden"))) ),否则objcopy无法将其设置为local,也就无法被strip -x移除,当然用strip -N也可以,就是麻烦。objcopy -G not_exist_sym libxxx.a会将除not_exist_sym之外所有符号设置为local,如果没有副作用,那就可以解决这个缺点。
2.当原始库需要被删除的符号是内部调用的符号(例如source1.c 中调用了source2.c的函数),不管是不是hidden,此符号都处于relocation,无法被strip移除,只能--redefine-sym --rename-section一个个修改混淆。即便如此,该符号的地址依然存在。
3.未被strip的local状态的符号可以被objdump nm看到,但不可被链接,实际上只要用objcopy --globalize-symbol=sym_name libxxx.a即可让其重新可链接。
4.库使用-ffunction-sections -fdata-sections编译时,即便strip了符号,section name依然存在。
方法2
#源码里,需要暴露的符号用__attribute((visibility("default"))),编译时增加参数
gcc -c *.c -o output.o -fvisibility=hidden
#链接,只保留default或protected的global符号
ld -r output.o --gc-sections --gc-keep-exported -o libxxx.o
gcc-ar rcs -o libxxx.o libxxx.a
缺点:
1.需要有源码
2.依然不会删除内部调用的符号