libgcc链接错误:DSO引用libgcc.a中隐藏符号__aarch64_swp1_acq_rel
问题翻译
我尝试链接一个无法控制的第三方共享库,该库存在未定义符号(nm输出):U __aarch64_swp1_acq_rel。该符号似乎在libgcc.a中定义:
[user@fedora ~]$ nm -a /usr/lib/gcc/aarch64-redhat-linux/12/libgcc.a | grep swp1_acq_rel 0000000000000000 T __aarch64_swp1_acq_rel [user@fedora ~]$ objdump -t /usr/lib/gcc/aarch64-redhat-linux/12/libgcc.a | grep swp1_acq_rel 0000000000000000 g F .text 000000000000002c .hidden __aarch64_swp1_acq_rel
但每次链接都会出现未定义符号的错误。我理解该符号对动态链接隐藏(烦请确认是否有误),想请教在所用共享库未定义该符号时,如何正确链接此libgcc符号?为何该符号会被隐藏?
问题确认:符号确实对动态链接隐藏
从objdump输出的.hidden标记可以确定,__aarch64_swp1_acq_rel是动态链接不可见的符号。这个标记会让链接器不把该符号加入动态符号表,因此动态链接器在加载时无法解析共享库对它的引用,这就是你链接报错的核心原因。
解决方法
1. 静态链接libgcc的对应模块
因为libgcc.a是静态库,你可以把包含目标符号的目标文件提取出来,直接加入链接流程:
- 先定位libgcc.a中包含该符号的.o文件:
找到对应的.o文件(通常是类似ar x /usr/lib/gcc/aarch64-redhat-linux/12/libgcc.a nm *.o | grep __aarch64_swp1_acq_relatomic-swp1.o的名称) - 在链接命令中,将这个.o文件放在第三方共享库之后,例如:
gcc your_code.c -o your_program /path/to/third-party.so ./atomic-swp1.o - 或者直接使用
-static-libgcc选项强制静态链接整个libgcc,自动包含所需符号:gcc your_code.c -o your_program /path/to/third-party.so -static-libgcc
2. 调整链接顺序与参数
如果直接用-lgcc链接,需要确保它出现在第三方共享库之后(链接器按顺序解析符号):
gcc your_code.c -o your_program /path/to/third-party.so -lgcc
如果还是不行,可以用--whole-archive参数强制链接libgcc.a的所有内容(注意后续用--no-whole-archive恢复默认行为):
gcc your_code.c -o your_program /path/to/third-party.so -Wl,--whole-archive -lgcc -Wl,--no-whole-archive
符号被隐藏的原因
__aarch64_swp1_acq_rel是GCC实现ARM64原子操作的内部私有符号,属于libgcc的底层实现细节。GCC将这类符号标记为.hidden的原因包括:
- 避免外部代码直接依赖内部函数,防止因GCC版本更新导致的ABI兼容性问题(这类内部符号的实现可能在不同版本中变化);
- 减少动态符号表的大小,提升链接和加载效率;
- 维护libgcc的封装性,确保上层代码通过标准原子操作接口(比如C11的
<stdatomic.h>)而非直接调用内部函数实现原子操作。
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

