如何知道程序需要什么版本的libc/libstdc++

2023-10-13 10:28:09 浏览数 (2)

总结

  • 一套系统折腾多套gcc、libc、libstdc 没必要,浪费时间。用对应版本的系统编译对应版本的二进制即可。一般软件对libc、libstdc 的要求都不会太高,系统别太老一般都能跑。
  • 如果系统太老,自带的libc太旧,新软件可能会编译失败(比如用了新的libc的函数),这种情况下如果是因为libc太久,可以直接升级系统,实在可下载libc给程序特供。
  • 如果因为libstdc 太旧(比如用了新的c 库函数),因为libstdc 是跟着gcc的,系统的gcc也比较旧了,可以更新gcc的版本,编译时需要执行用新的gcc,但很可能编译时还回去去找老的gcc和老的stdlibc 库,这就需要看程序的怎么编译的了,改下编译器、引用库路径等。

C 的版本管理简单粗暴,像libc这种基础库如果需要多版本,用起来非常不方便,但c/c 基础库都是向下兼容的,最好的方式就是用一套比较新的系统,带着新的libc,再安装一套和系统版本同年代的新一点的gcc编译器即可,可满足大部分的使用场景,避免一套环境上折腾多套libc、libstdc ,经验之谈:非常麻烦性价比很低!

libc.so

系统一定会自带libc.so,因为这是C的基础库,内核和所有程序都会依赖系统自带libc.so。

随便一个程序看下依赖库,都能看到Libc的影子:

代码语言:javascript复制
# ldd /usr/bin/echo
	...
	...
	libc.so.6 => /lib64/libc.so.6 (0x00007fa004df6000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007fa004bf2000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa0053c5000)

注意:程序用的时候都会用/lib64/libc.so.6的名字,而libc.so.6会指向哭啼某个版本的libc。

查看所依赖的libc版本,可以看出当前Libc的版本是2.28。而Libc是向下兼容的,从库中定义的一些字符串常量可以知道兼容哪些版本:

  • 当前是2.28
  • 向下兼容到2.3
代码语言:javascript复制
$ ll /lib64/libc.so.6
lrwxrwxrwx 1 root root 12 Nov 24  2022 /lib64/libc.so.6 -> libc-2.28.so

$ strings /lib64/libc.so.6 | grep -E '^GLIBC' | sort
GLIBC_2.10
GLIBC_2.11
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.23
GLIBC_2.24
GLIBC_2.2.5
GLIBC_2.25
GLIBC_2.25
GLIBC_2.2.6
GLIBC_2.2.6
GLIBC_2.26
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.28
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.5
GLIBC_2.6
GLIBC_2.6
GLIBC_2.7
GLIBC_2.7
GLIBC_2.8
GLIBC_2.8
GLIBC_2.9
GLIBC_2.9
GLIBC_PRIVATE

/lib64/目录是短连接,实际位置:

代码语言:javascript复制
$ ll /lib64
lrwxrwxrwx 1 root root 9 Dec 21  2021 /lib64 -> usr/lib64

$ ll /usr/lib64/ | grep libc.so
-rw-r--r--  1 root root      253 Nov 24  2022 libc.so
lrwxrwxrwx  1 root root       12 Nov 24  2022 libc.so.6 -> libc-2.28.so

ldd的版本和libc是配套的:

代码语言:javascript复制
$ ldd --version
ldd (GNU libc) 2.28
Copyright (C) 2018 Free Software Foundation, Inc.

编译器用的Libc版本:

代码语言:javascript复制
$ gcc -print-file-name=libc.so
/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/libc.so

libstdc 与gcc

  • libstdc 是c 的标准库文件,注意libstdc 是和gcc一起编译安装的。
  • 自己编译安装的gcc是不会安装libc的,libc可以单独下载升级。
  • linux系统内核、自带工具会依赖libc,所以libc是必须存在的;但不依赖libstdc ,所以libstdc 可以不安装。

使用g 编译的c 程序会依赖c 标准库libstdc .so.6

代码语言:javascript复制
$ ldd llvm-as
	...
	libstdc  .so.6 => /lib64/libstdc  .so.6 (0x00007f4cf5ae0000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f4cf575e000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4cf5546000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f4cf5180000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f4cf68bc000)

libstdc .so.6的名字也是用短连接指向真正的库文件:

代码语言:javascript复制
$ ll /lib64/libstdc  .so.6
lrwxrwxrwx 1 root root 19 May 24 22:05 /lib64/libstdc  .so.6 -> libstdc  .so.6.0.25

$ strings /usr/lib64/libstdc  .so.6 | grep LIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25
GLIBCXX_DEBUG_MESSAGE_LENGTH
GA GLIBCXX_ASSERTIONS

程序需要什么版本的libc和libstdc

以llvm为例

代码语言:javascript复制
$ readelf -s llvm-ar | grep -oE "GLIBCXX_.*|GLIBC_.*" | sort | uniq
GLIBCXX_3.4
GLIBCXX_3.4 (6)
GLIBCXX_3.4.11 (14)
GLIBCXX_3.4.14 (26)
GLIBCXX_3.4.15 (11)
GLIBCXX_3.4.18 (22)
GLIBCXX_3.4.19 (21)
GLIBCXX_3.4.20 (5)
GLIBCXX_3.4.21 (8)
GLIBCXX_3.4.9 (13)
GLIBC_2.14
GLIBC_2.14 (7)
GLIBC_2.15 (23)
GLIBC_2.2.5
GLIBC_2.2.5 (15)
GLIBC_2.2.5 (18)
GLIBC_2.2.5 (3)
GLIBC_2.2.5 (4)
GLIBC_2.3
GLIBC_2.3 (17)
GLIBC_2.3 (9)
GLIBC_2.6
GLIBC_2.6 (10)

可以看出llvm-ar需要:

  • libc的版本为:2.15
  • libcxx的版本为:3.4.21

而当前系统提供:

  • libc的最新版本:2.28
  • libcxx的版本:3.4.25
代码语言:javascript复制
strings /usr/lib64/libstdc  .so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25

strings /lib64/libc.so.6 | grep -E '^GLIBC' | sort
GLIBC_2.10
GLIBC_2.11
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.18
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.2.6
GLIBC_2.22
GLIBC_2.23
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.25
GLIBC_2.26
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.28
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.5
GLIBC_2.6
GLIBC_2.6
GLIBC_2.7
GLIBC_2.7
GLIBC_2.8
GLIBC_2.8
GLIBC_2.9
GLIBC_2.9

可以满足要求。

0 人点赞