逆天改命之装第二个 glibc

问题

如果你在用一个很老的系统,你可能遇到:

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

Glibc 一般是由系统底层来维护的,要运行必须升级系统。

但!是!服务器是公用的集群,没有root,升级不了。

尝试

于是尝试逆天改命装第二个 glibc:

第一步:

wget http://mirrors.ustc.edu.cn/gnu/libc/glibc-2.39.tar.gz
tar -xvzf glibc-2.39.tar.gz
cd glibc-2.39
mkdir build
cd build
../configure --prefix="$HOME/opt/glibc/2.39"
make -j 16
make -j 16 install

然后你 90% 概率会遇到以下错误之一:

These critical programs are missing or too old: make

需要使用新版 make. 自行编译 / 安装

…/sysdeps/x86_64/multiarch/memchr-evex-base.S:229: Error: no such instruction: vpcmpneqb (64 * 4)(%rdi),%zmm17,%k1’

binutils版本不匹配,需要和glibc版本相同,然后修改PATH使运行ld调用的是这个版本的binutils中的ld:

wget http://ftp.gnu.org/gnu/binutils/binutils-2.39.tar.gz
tar -xvzf binutils-2.39.tar.gz
cd binutils-2.39
mkdir build
cd build
../configure --prefix="$HOME/opt/binutils/2.39"
make -j 16
make -j 16 install

makeinfo 相关错误:

没有安装 texinfo, 安装编译后 $PATH 指向 bin 解决

运行

装好后,需要修改你要运行的程序:

第一步,将编译器移出:

mv $HOME/opt/glibc/2.39/lib/ld-linux-x86-64.so.2 $HOME/opt/glibc/2.39/ld-linux-x86-64.so.2

第二步,安装 patchelf(推荐用 spack 安装)

spack install patchelf
spack load patchelf

第三步,修改程序

patchelf --print-rpath xxx

# 如果没有 RPATH
patchelf --set-rpath $HOME/opt/glibc/2.39/lib xxx

# 如果有 RPATH
patchelf --set-rpath $HOME/opt/glibc/2.39/lib:/original/rpath xxx

# 设置解析器
patchelf --set-interpreter $HOME/opt/glibc/2.39/ld-linux-x86-64.so.2 xxx

第四步,尝试运行

xxx

如果此时提示库找不到,但是实际上在系统库中,说明系统库路径没有注册到新的 glibc中:

# 增加系统目录
echo "/lib64" > $HOME/opt/glibc/2.39/etc/ld.so.conf
$HOME/opt/glibc/2.39/sbin/ldconfig -f $HOME/opt/glibc/2.39/etc/ld.so.conf -C $HOME/opt/glibc/2.39/etc/ld.so.cache

# 检查已注册的系统库路径
$HOME/opt/glibc/2.39/sbin/ldconfig -p

简单记录以供各位需要改名的朋友们参考。

16 个赞

佬友用过nix吗 安装个nix包管理似乎可以解决这个问题

嗯,我知道,可惜的是大部分的集群系统RHEL/Ubuntu/Debian/Arch默认都没有允许非特权用户的用户命名空间:

这个需要 root 才能启用,所以问题又回去了。

不过感谢你的思路。

1 个赞

可以呀,大佬就是大佬

最近用麒麟的服务器好像有类似的问题,研究一下,谢谢佬友分享

这是我在deepin论坛的回帖,我粘贴过来,供大家参考
https://bbs.deepin.org/phone/zh/post/282254


实际上,我找到了一个看起来更加优雅~~暴力~~的解决方案。

https://github.com/corsix/polyfill-glibc
这个项目能够修改编译好的可执行文件,以移除GLIBC的版本依赖。尽管很多时候,移除了GLIBC依赖也无法在旧的GLIBC上运行,但很多时候,这就足够了。

即使这样不够,比如还有GLIBCXX的版本依赖,或者旧版glibc缺少函数改了也没办法的情况。

那么它还有另一个功能,通过 --set-interpreter参数,它可以修改可执行文件默认调用的 ld-linux-$ARCH.so.1链接器路径,从而避免使用容器或命名空间。

所以我只需要把additional-base-lib打包进去,修改程序的–set-interpreter,就可以简单的使用

LD_PRELOAD=./lib/additional-base-lib/libc.so.6 LD_LIBRARY_PATH=./lib/additional-base-lib executable

这样的命令来运行可执行文件。它也可以修改动态库,不过不建议这么做,改的多了总会出问题。


下面是我的一个改造成果,Aethersx2,著名的PS2模拟器,闭源,作者跑路,采用qt6编译。本体依赖GLIBC2.29和GLIBCXX_3.4.26,同时qt6本身也有同样的依赖。

通过集成作者的additional-base-lib(只需要库文件),修改–set-interpreter以调用相对路径的 ld-linux-aarch64.so.1,替换其他依赖库包括qt6到debian10能用的版本,然后通过上述命令优雅的本地运行。不需要容器,纯绿色打包,只需要一个启动脚本。而这玩意以前只有个appimage,而且并不能运行。

3 个赞

跑题了,怎么可以在linux论坛发linux内容呢
:tieba_025:

好麻烦啊!感谢分享 Linux 编译姿势~

这个好东西啊

哪里都可以跑

1 个赞

感谢,这个经常能碰到

mark

3 个赞

厉害的 :+1:

常规操作了:grinning_face:,在古董系统上跑闭源软件的时候这种事没少干过:face_exhaling:

此话题已在最后回复的 30 天后被自动关闭。不再允许新回复。