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文件:
- 根目录
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
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
相关产品推荐
相关产品推荐

