为何移除符号信息后,编译生成的SO文件仍可正常运行?
为什么strip掉非导出符号的SO仍能正常运行?
你忽略的核心点在于符号表的作用范围,以及内部函数调用的地址绑定时机,具体拆解如下:
符号表不是内部调用的运行必需项
--strip-all删除的是SO的符号表(.symtab)和动态符号表(.dynsym)中的非导出符号,但这些符号仅用于链接阶段的地址解析、调试工具(如gdb)定位,或者外部程序引用SO的函数。对于SO内部的函数调用,链接器在生成SO时已经完成了地址绑定——编译器会将内部函数调用编译为PC相对寻址或直接内存偏移,运行时不需要再通过符号表查找地址。内部调用属于静态绑定范畴
只有两类场景需要动态符号表:一是外部程序调用SO的导出函数(动态链接器需要通过符号找到对应地址);二是SO内部调用其他动态库的函数(通过PLT/GOT机制延迟绑定)。而SO内部的函数调用在链接阶段就把地址硬编码到指令里了,完全不依赖符号表。导出符号保留的必要性
你看到的保留符号都是对外暴露的导出函数,这些是动态链接器必须的——外部程序加载SO时,需要通过这些符号找到要调用的函数入口。非导出符号没有被外部访问的需求,所以删除后完全不影响SO自身的执行逻辑。
可以用两个命令验证这个逻辑:
- 执行
readelf -s test.so,会看到非导出符号已被移除; - 执行
objdump -d test.so反汇编内部函数,能看到调用指令是直接跳转到内存偏移(比如call 0x1234),而非通过PLT表(比如call plt+0x10),这就证明地址在链接时已经确定,不需要运行时符号表。
内容的提问来源于stack exchange,提问作者SongpaGu
相关产品推荐
相关产品推荐

