You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GNU libc 2.31时出现xdr_string未定义引用问题求助

关于glibc 2.31中xdr_*符号未定义引用的问题

问题背景

在使用glibc 2.31-7.30.x86_64编译链接时,出现xdr_string未定义引用错误。检查发现该版本glibc中所有xdr_*方法均带有@GLIBC_2.2.5版本后缀;而glibc 2.22中这些符号无后缀,可正常链接。当前依赖无法修改的第三方库libnl,需要解决以下问题:

  1. 此现象是否为glibc 2.31的预期情况?
  2. 如何正确解析xdr_string@GLIBC_2.2.5引用?
  3. 当ld指定-lc时,如何解析为libc.so.6?

glibc 2.31下的符号信息

% rpm -qf libc.so.6
glibc-2.31-7.30.x86_64
% nm libc.so.6 |grep "\b xdr_"
0000000000126970 T xdr_accepted_reply@GLIBC_2.2.5
0000000000132850 T xdr_array@GLIBC_2.2.5
00000000001285b0 T xdr_authdes_cred@GLIBC_2.2.5
0000000000128630 T xdr_authdes_verf@GLIBC_2.2.5
0000000000124b20 T xdr_authunix_parms@GLIBC_2.2.5

glibc 2.22下的符号信息

% rpm -qf libc.so.6
glibc-2.22-114.22.1.x86_64
% nm libc.so.6 |grep "\b xdr_"
00000000001125d0 T xdr_accepted_reply
000000000011d3d0 T xdr_array
0000000000114020 T xdr_authdes_cred
00000000001140b0 T xdr_authdes_verf
00000000001108a0 T xdr_authunix_parms

链接错误信息

% g++ main.c libnl.a -ldl -lpthread libmycrypto.so
/usr/x86_64-suse-linux/bin/ld: libnl.a(nl2.o): in function `xdr_stringUC16':
/bas/src/flat/nl2.c:559: undefined reference to `xdr_string'
/usr/x86_64-suse-linux/bin/ld: /bas/src/flat/nl2.c:566: undefined reference to `xdr_string'
/usr/x86_64-suse-linux/bin/ld: /bas/src/flat/nl2.c:579: undefined reference to `xdr_string'
/usr/x86_64-suse-linux/bin/ld: /bas/src/flat/nl2.c:579: undefined reference to `xdr_free'
collect2: error: ld returned 1 exit status

问题解答

1. 此现象是否为glibc 2.31的预期情况?

是预期行为。glibc的符号版本化机制会为部分符号添加版本后缀,xdr_*这类RPC相关符号在2.31版本中已经启用了版本标记,而2.22版本中尚未添加,因此出现符号名称不一致的情况。符号版本化是glibc为了保证ABI兼容性的设计,确保不同版本glibc编译的程序能互相兼容运行。

2. 如何正确解析xdr_string@GLIBC_2.2.5引用?

有三种可行的解决方法:

  • 显式链接RPC库:xdr_*属于RPC模块,修改链接命令添加-lrpc选项,让链接器正确定位带版本后缀的符号:
    g++ main.c libnl.a -ldl -lpthread libmycrypto.so -lrpc
    
  • 编写符号别名封装:创建一个简单的C文件,将无版本后缀的符号映射到带版本的符号,编译后加入链接:
    // alias_xdr.c
    #include <rpc/xdr.h>
    
    void xdr_free(xdrproc_t proc, char *objp) {
        xdr_free@GLIBC_2.2.5(proc, objp);
    }
    
    bool_t xdr_string(XDR *xdrs, char **cpp, u_int maxsize) {
        return xdr_string@GLIBC_2.2.5(xdrs, cpp, maxsize);
    }
    
    编译并链接:
    gcc -c alias_xdr.c
    g++ main.c libnl.a alias_xdr.o -ldl -lpthread libmycrypto.so
    
  • 使用链接器脚本重定向:编写链接器脚本,将无版本符号指向带版本的符号:
    PROVIDE(xdr_string = xdr_string@GLIBC_2.2.5);
    PROVIDE(xdr_free = xdr_free@GLIBC_2.2.5);
    
    链接时指定脚本:
    g++ main.c libnl.a -ldl -lpthread libmycrypto.so -T alias_xdr.ld
    

3. 当ld指定-lc时,如何解析为libc.so.6?

这是链接器的默认搜索规则导致的:

  • 当使用-l选项时,链接器会自动将-lc转换为查找libc.so(共享库)或libc.a(静态库)。
  • 系统中libc.so是一个符号链接,默认指向实际的glibc共享库文件libc.so.6(6是glibc的主版本号)。
  • 链接器会在预设的库搜索路径(如/lib64、/usr/lib64)中找到libc.so,跟随符号链接定位到libc.so.6,完成解析。

内容的提问来源于stack exchange,提问作者Zippon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:55:39