如何通过版本脚本让ld剥离本地符号,避免单独执行strip?
我用GCC编译共享ELF库时,添加了-Wl,--version-script=version.script参数,版本脚本内容如下:
MYLIB_1.0 { global: the_only_symbol_i_want; local: *; };
该配置已达到预期效果:仅the_only_symbol_i_want被导出为全局符号,其余所有符号均为本地符号。
但我还希望直接剥离这些本地符号。查阅ld手册得知可使用-Wl,--discard-all参数,尽管该参数命名不够准确,文档说明它实际是丢弃所有本地符号而非全部符号,但将其与--version-script配合使用时,完全没有效果。
单独执行strip --discard-all mylib.so可以实现需求,但我希望避免单独运行strip命令。请问是否有办法让ld直接实现该需求?版本脚本是否支持discard:选项?
1. 版本脚本的discard:选项可直接实现需求
你可以在版本脚本中添加discard:段来丢弃不需要的符号,无需额外的--discard-all参数。修改后的版本脚本如下:
MYLIB_1.0 { global: the_only_symbol_i_want; local: *; }; discard { *; };
这个脚本会先将除指定全局符号外的所有符号标记为本地,再直接丢弃所有剩余的本地符号。编译时只需保留-Wl,--version-script=version.script参数即可,无需添加--discard-all。
2. 解释--discard-all与版本脚本配合无效的原因
当你通过版本脚本将符号标记为local:后,这些符号会被归类为本地符号,但ld的--discard-all仅会丢弃未被引用的本地符号,而非所有本地符号。如果你的本地符号之间存在相互引用,ld就不会丢弃它们,这就是为何看起来没有效果。而strip --discard-all是直接移除所有本地符号,无论是否被引用,这与ld的--discard-all行为存在本质区别。
3. 验证方法
编译完成后,可通过readelf -s mylib.so查看符号表,确认仅the_only_symbol_i_want存在,其余本地符号已被丢弃。
内容的提问来源于stack exchange,提问作者Timmmm

