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

Ubuntu22.04中链接自定义编译glibc-2.31后段错误原因排查

问题分析:Ubuntu22.04编译glibc-2.31/2.32运行段错误

环境与编译配置

  • 运行环境:WSL x86-64 Ubuntu22.04 LTS,系统默认glibc版本为2.35
  • 编译工具:gcc/g++ 11.4.0
  • glibc-2.31编译配置命令:
$ /home/<username>/glibc-src/glibc-2.31/configure --prefix=/home/<username>/glibc-2.31 --disable-werror --enable-kernel=3.2 --host=x86_64-linux-gnu --build=x86_64-linux-gnu CC=gcc CXX=g++

编译时的手动修改

为解决编译阶段的链接错误,手动修改了两个Makefile文件:

  1. 根目录Makefile:
# 注释原577-581行逻辑,强制指定C版本链接程序
577 #ifeq (,$(CXX))
578 #LINKS_DSO_PROGRAM = links-dso-program-c
579 #else
580 #LINKS_DSO_PROGRAM = links-dso-program
581 #endif
582 LINKS_DSO_PROGRAM = links-dso-program-c
  1. support/Makefile:
# 注释原191-196行逻辑,强制指定C版本链接程序
191 #ifeq (,$(CXX))
192 #LINKS_DSO_PROGRAM = links-dso-program-c
193 #else
194 #LINKS_DSO_PROGRAM = links-dso-program
195 #LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind)
196 #endif
197 LINKS_DSO_PROGRAM = links-dso-program-c

测试情况与错误现象

编译安装完成后,编译测试程序并链接自定义glibc:
测试代码test.c:

// test.c
int main()
{
    return 0;
}

编译命令:

$ gcc -o test test.c -L/home/<username>/glibc-2.31/lib -Wl,-rpath=/home/<username>/glibc-2.31/lib -Wl,-dynamic-linker=/home/<username>/glibc-2.31/lib/ld-linux-x86-64.so.2

运行程序触发段错误,GDB调试信息显示:

  • 错误发生在ld-linux-x86-64.so.2的_dl_lookup_symbol_x函数内mov %fs:0x10, %rax指令处
  • 调用栈指向查找__vdso_clock_gettime符号的过程

额外现象:

  • Ubuntu22.04编译glibc-2.32同样出现段错误,glibc-2.33可正常运行
  • Ubuntu20.04编译的glibc-2.31在本地及Ubuntu22.04中均正常,且无需修改上述Makefile

原因分析

1. 新内核与旧版glibc的vDSO兼容性问题

Ubuntu22.04的内核版本远高于编译时指定的--enable-kernel=3.2,而glibc-2.31/2.32对新内核的vDSO(虚拟动态共享对象)处理存在缺陷:

  • 新内核调整了vDSO的结构或__vdso_clock_gettime符号的查找逻辑,旧版glibc的动态链接器在访问fs段寄存器关联的线程本地存储(TLS)时出现非法内存访问,直接触发段错误。
  • glibc-2.33开始修复了对新内核vDSO的适配逻辑,因此可以正常运行。

2. 手动修改Makefile的副作用

强制将LINKS_DSO_PROGRAM设为C版本链接程序,跳过了C版本工具的编译,可能导致glibc编译过程中部分依赖C的辅助功能未正确生成,间接破坏了动态链接器符号查找的完整性。而Ubuntu20.04默认gcc 9与glibc-2.31兼容性更好,无需修改Makefile即可完成编译,因此没有引入该问题。

3. 高版本编译器的适配问题

gcc 11.4.0属于较新的版本,glibc-2.31发布时并未针对该版本做适配,编译过程中可能生成了旧版glibc无法正确处理的代码,尤其是TLS相关指令,导致动态链接器运行时访问非法内存。

总结

问题核心是Ubuntu22.04的新内核、高版本编译器与glibc-2.31/2.32的兼容性不匹配,手动修改Makefile进一步加剧了动态链接器的功能缺陷。glibc-2.33及以后版本修复了相关兼容性问题,而Ubuntu20.04的环境更贴合glibc-2.31发布时的目标环境,因此可以正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:36:03