背景
在工作过程中,我们经常会遇到可执行程序依赖的glibc跟当前运行环境的版本不兼容,导致应用程序无法运行,比如:
/lib64/libc.so.6: version `GLIBC_2.14’ not found
原因是运行环境的glibc的版本比编译环境的glibc的版本低。
几种可行的方法
1. 升级当前运行环境的glibc
2. 静态编译
将依赖高版本glibc的可执行程序进行静态编译
3. 修改引用了高版本的glibc的elf文件
4. 使用高版本glibc的容器
使用一个运行有高版本glibc的容器,将可执行程序运行在容器里
5. 通过环境变量控制可执行程序对动态库的加载
将可执行程序依赖的动态库提取出来,然后通过LD_LIBRARAY_PATH指定动态库的加载路径,然后用其中的动态链接器来执行可制成程序,下面以qemu为例,具体步骤如下.
在编译环境下找到qemu依赖的动态库
$ ldd qemu-system-x86_64 linux-vdso.so.1 (0x00007ffc26162000) libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007fc520b46000) libdw.so.1 => /lib/x86_64-linux-gnu/libdw.so.1 (0x00007fc520ae7000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc520acb000) libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007fc520a9e000) libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007fc5208bd000) libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007fc52085d000) libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fc520731000) libbpf.so.0 => /lib/x86_64-linux-gnu/libbpf.so.0 (0x00007fc5206e3000) libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007fc5206a9000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fc520679000) libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007fc520673000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007fc520660000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc520659000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc52050a000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc5204ef000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc5204cc000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc5202da000) /lib64/ld-linux-x86-64.so.2 (0x00007fc521d5a000) libelf.so.1 => /lib/x86_64-linux-gnu/libelf.so.1 (0x00007fc5202be000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc5202b6000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007fc52028d000) libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007fc52022d000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fc520202000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc5201e6000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007fc5201da000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fc520165000) libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007fc52010e000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fc52007d000)
将qemu依赖的动态库全部拷贝到一个目录下
- 将上面的输出放到一个文件里,如下:
$ cat deps.txt libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f719a1ce000) libdw.so.1 => /lib/x86_64-linux-gnu/libdw.so.1 (0x00007f719a16f000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f719a153000) libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f719a126000) libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f7199f45000) libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f7199ee5000) libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f7199db9000) libbpf.so.0 => /lib/x86_64-linux-gnu/libbpf.so.0 (0x00007f7199d6b000) libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007f7199d31000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f7199d01000) libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f7199cfb000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f7199ce8000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f7199ce1000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7199b92000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7199b77000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7199b54000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7199962000) libelf.so.1 => /lib/x86_64-linux-gnu/libelf.so.1 (0x00007f7199946000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f719993e000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f7199915000) libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f71998b5000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f719988a000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f719986e000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f7199862000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f71997ed000) libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f7199796000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f7199705000)
- 编写一个脚本,将动态库拷贝到指定目录下:
#!/bin/bash rm -rf libs mkdir libs while read line do lib_path=`echo $line | awk '{print($3)}'` if [ -z "$lib_path" ];then continue fi cp $lib_path ./libs done < deps.txt chmod +x libs/*
- 把动态链接器也拷贝到libs下
$ cd libs/ $ cp /lib64/ld-linux-x86-64.so.2 .
测试
- 使用下面的命令来运行
**#!/bin/bash kvm_path=`realpath $0` kvm_path=`dirname $kvm_path` abslibdir=$kvm_path/libs loader=$abslibdir/ld-linux-x86-64.so.2 binary=$kvm_path/qemu-system-x86_64 LD_LIBRARY_PATH="$abslibdir/" "$loader" "$binary" "$@" # exec "$loader" --library-path "$abslibdir" "$binary" "$@" BASH 复制 全屏
- 测试
$ ./run.sh --version QEMU emulator version 8.0.0 Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
完。