非编译方式解决GLIBC版本兼容性问题

发布时间 2023-07-18 20:32:28作者: 易先讯

摘要:背景客户在CentOS 7.6上安装昇腾910b驱动后,执行hccn_tool命令,报错如下:PlainBashC++C#CSSDiffHTML/XMLJavaJavascriptMarkdownPHPPythonRubySQL./hccn_tool: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by ./hccn_tool)原因分析安装NPU驱动后,其他命令均可以正常执行,只有hccn_tool提示GLIBC版本找不到,通常原因是该驱动hccn_tool部分是在高版本的glibc系统上构建的,在包含低版本glibc的系统上,则会因为缺少对应

背景

客户在CentOS 7.6上安装昇腾910b驱动后,执行hccn_tool命令,报错如下:

./hccn_tool: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by ./hccn_tool)

 

原因分析

安装NPU驱动后,其他命令均可以正常执行,只有hccn_tool提示GLIBC版本找不到,通常原因是该驱动hccn_tool部分是在高版本的glibc系统上构建的,在包含低版本glibc的系统上,则会因为缺少对应的符号表而提示not found。

 

具体证明过程如下:

 

查看链接的glibc文件

 

查看链接的glibc中支持的glibc版本

说明确实不包含GLIBC_2.25版本

 

构建最小原型验证

考虑到驱动hccn_tool关联较多跟其业务相关的内容,并且我们没有910b的验证环境,我们只能讲问题最小化,构建一个最小的验证原型来测试我们的解决思路。

 

首先,获取驱动910b的软件包,将其解压缩提取到任意目录,直接找到对应的hccn_tool文件,直接执行报错,接下来分析具体报错函数。

 

查看具体不支持的函数

说明hccn_tool中使用了高版本glibc中才有的函数getentropy,那么我们使用该函数写一个最小的demo来验证一下。

 

编译一个调用getentropy的简单程序验证

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main() {
unsigned char buffer[16];
if (getentropy(buffer, sizeof(buffer)) == -1) {
perror("getentropy");
exit(EXIT_FAILURE);
}
printf("Random bytes: ");
for (int i = 0; i < sizeof(buffer); i++) {
printf("%02x", buffer[i]);
}
printf("\n");
return 0;
}

 

使用gcc编译验证

当前系统上glibc的版本最高只支持2.17,并不包含getentropy函数,在包含较高版本glibc的环境上(比如ubuntu20.04)编译成功,将其文件拷贝到centos7.6上执行,运行直接报错GLIBC_2.25 not found

 

由此,我们得到了一个最小原型的验证环境。

 

寻找解决方案

针对该问题,网上有大量的搜索结果,通常是升级glibc,同时给出大量警告--不要升级。

原因是glibc升级后,增加新的函数的同时,也会移除旧的函数符号表,系统上很多系统命令可能会依赖旧的函数符号表,导致系统很多命令直接无法执行,直接提示Segmentation fault,进而整个系统完全没法使用

 

既然有大量的失败案例,我们直接抛弃了该方式进行验证。

同时,我们没有NPU驱动的源码,所以不直接尝试编译链接的方式来解决问题。

能不能只在运行该可执行文件时链接高版本glibc呢?我们来试验一下。

 

我们从Ubuntu20.04上拷贝了对应的libc文件,并创建了对应的软连接,修改LD_LIBRARY_PATH来指向glibc所在的目录,直接执行我们的程序,直接Segmentation fault

并且执行ldd ./test也直接报错Segmentation fault。

 

unset掉LD_LIBRARY_PATH,查看链接文件:

 

只依赖libc啊,难道跟ld也有关?查阅资料,发现确实是这么回事,ld和glibc都必须版本配套,拷贝ld,修改LD_LIBRARY_PATH后依然段错误。

 

查看资料发现,ld-linux-x86-64.so.2是在编译时硬编码进去的,证明如下:

 

换一种方式执行,就可以了

 

回到hccn_tool目录,直接验证:

 

根据报错信息,依次添加对应版本的so文件即可,最终执行成功

 

最终,我们找到了一种不升级glibc解决多版本glibc兼容性问题的的方式。

 

参考链接:https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/44710599#44710599