如何确定系统使用的userland C库?需要此信息的可能原因包括:
ldd
。我不确定是否otool --version
可以提供相同的信息。
如何确定系统使用的userland C库?需要此信息的可能原因包括:
ldd
。我不确定是否otool --version
可以提供相同的信息。
Answers:
GNU / Linux系统通常使用glibc(Fedora / Redhat家族,Arch)或它的近亲,例如liblibc(Debian / Ubuntu家族)。由于eglibc现在已被合并回glibc(请参阅“新闻”下创建的EGLIBC 2.19分支),因此在不久的将来它们将再次全部变为glibc。
检查确切版本的最简单方法是ask ldd
,它随C库一起提供。
在Fedora 20上:
> ldd --version
ldd (GNU libc) 2.18
那就是glibc 2.18。
在Raspbian上(用于ARMv6 Broadcom SoC的Debian 7端口):
> ldd --version
ldd (Debian EGLIBC 2.13-38+rpi2) 2.13
那是eglibc 2.13。
如果您出于某种原因混合或匹配了某些部分,或者不确定ldd
,则可以直接查询C库。
> whereis libc.so
libc: /usr/lib64/libc.a /usr/lib64/libc.so /usr/share/man/man7/libc.7.gz
这些都不是可执行文件,但是它们提供了有关在哪里找到的线索。
> $(find /usr/lib64/ -executable -name "*libc.so*") --version
GNU C Library (GNU libc) stable release version 2.18, by Roland McGrath et al.
但是,它不一定那么容易,因为C库不必位于whereis
可以找到它的地方。
> whereis libc.so
libc: /usr/share/man/man7/libc.7.gz
不幸的是,手册页没有提供版本号。 ldd
仍然派上用场,因为系统上任何有效的,动态链接的可执行文件(例如,中的几乎所有内容/usr/bin
)都将链接到C库。
> ldd /usr/bin/touch
/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6eed000)
librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6ed0000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6da1000)
/lib/ld-linux-armhf.so.3 (0xb6efb000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6d82000)
libc.so.6
在第三行。
> /lib/arm-linux-gnueabihf/libc.so.6 --version
GNU C Library (Debian EGLIBC 2.13-38+rpi2) stable release version 2.13, by Roland McGrath et al.
/lib/`uname -m`*
路径。因此,便携式的办法是:find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version
。感谢您的解释。
一个系统实际上并不限于一个C库。但是,大多数主要只使用一种,这也将是默认编译器使用的一种。而且由于您正在下载要编译的源代码,因此您正在担心的是那一个。
从一个简单的程序开始:
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
使用将用于源代码的编译器对其进行编译,然后使用该代码ldd
找出C库的位置:
$ ldd ./libc-test
linux-vdso.so.1 (0x00007fff2e5fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c8ad98000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c8b171000)
现在,您具有C库的路径。您可以在包管理器中查找它以找到包(例如dpkg -S /lib/x86_64-linux-gnu/libc.so.6
或rpm -q -f /lib/x86_64-linux-gnu/libc.so.6
)。
至少在eglibc / glibc的情况下,可以运行它:
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
⋮
最后,objdump -p /lib/x86_64-linux-gnu/libc.so.6
通过查看“ 版本定义”部分,您可以查看是否可以从中获得线索:
Version definitions:
1 0x01 0x0865f4e6 libc.so.6
2 0x00 0x09691a75 GLIBC_2.2.5
3 0x00 0x09691a76 GLIBC_2.2.6
⋮
21 0x00 0x06969197 GLIBC_2.17
GLIBC_2.16
22 0x00 0x06969198 GLIBC_2.18
GLIBC_2.17
23 0x00 0x0963cf85 GLIBC_PRIVATE
GLIBC_2.18
请注意,GLIBC_2.18符号在列出的符号中如何具有最新的版本号,并且库版本确实为2.18。不过它是eglibc(它的目标是与glibc 2.18二进制兼容,因此它使用相同的符号版本)。
您也可以尝试使用它strings
来查找有关它的信息。您需要指定更长的最小长度(-n
),或使用grep搜索内容:
$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep 'version [0-9]'
$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep -iC1 'copyright'
两者都适用于此eglibc。
注:Debian软件包工具dpkg-shlibdeps
使用objdump
引擎盖下,在Debian的包库存储的符号信息,以确定在构建时由二进制Debian软件包所需的依赖的最低版本一起。基本上,它查看二进制Debian软件包导出的符号,然后找到包含这些符号的库的最低版本。
显而易见的答案(虽然不是最全面的)是检查软件包管理器,例如
rpm -qi glibc
dpkg -l libc6
(遗憾的是,glibc没有pkconfig .pc
文件,因此pkgconfig --modversion glibc
没有运行者。)另请参见@Gnouc的出色getconf
建议。
最简单的情况是使用gcc + glibc,而我最常使用的情况是执行libc.so
,如此处其他一些答案所述。无需传递任何参数,默认情况下会输出其版本。这可以追溯到glibc-2.1(glibc-2.0 seg-faults,尽管回溯到那时,您可以检查(现已退休)glibcbug
脚本以确认版本)。此方法还可以与musl-libc的最新版本(> 0.9.15)配合使用(3月20日今天才发布1.0)。它不能与uClibc一起使用,它会出现段错误。
准确说明gcc
要执行的操作的一种简单方法是编译:
#include <gnu/libc-version.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("%s %s\n",gnu_get_libc_version(),gnu_get_libc_release());
printf("glibc v%i %i.%i\n",__GNU_LIBRARY__,__GLIBC__,__GLIBC_MINOR__);
return 0;
}
(对于glibc,<stdio.h>
包含<features.h>
用于定义相关GLIBC宏<gnu/libc-version.h>
的函数声明需要使用。)
假设您使用的是正确的编译器(和标志),那么这将捕获更复杂的情况(多个libc和/或多个编译器)。(我怀疑它虽然不能正确区分eglibc和glibc。)
如果确定使用的是glibc(或eglibc),则(对不起,这是不正确的)。ld
还将确认版本
如果__GNU_LIBRARY__
未定义,您将得到错误,那么该是计划B的时候了。
gcc -dumpmachine
可能会有所帮助,例如,对于uclibc,它-uclibc
可能有一个后缀gcc -dumpspecs | grep dynamic-linker
。这也可能暗示着ABI。
gcc -print-file-name=libc.so
会告诉您编译器将使用哪个文件“ -lc
”,这几乎可以肯定是gcc安装程序中的链接描述文件,您可以将其阅读为纯文本。它将显示前往的确切路径libc.so
。如果您传递的标记是-m32
或,这也将起作用-m64
。
在事件您使用uClibc的(13759的OpenWRT多),它定义__UCLIBC_MAJOR__
,__UCLIBC_MINOR__
和__UCLIBC_SUBLEVEL__
以及__UCLIBC__
在<features.h>
,所以它很容易检测到使用在上述C代码片段一个微小变化。为了兼容性,uClibc还可以定义上面使用的GNU / GLIBC宏,目前它假装为glibc-2.2。当前不实现gnu_get_libc_X()
的功能,但它确实实现getconf
其还可能误导(我怀疑它返回一个空的答案getconf GNU_LIBC_VERSION
,我的体型ENV今天生闷气,所以我无法证实。)
在极少数情况下,如果您使用Dietlibc,则运行diet -v
将显示版本。
(FWIW,使用autoconf的软件已经使用了几年,与未检查的glibc功能相比,我对未检查gcc
和g++
要求的问题更多。)
GNU libc(大多数Linux发行版以一种形式或另一种形式使用)竭尽全力保持严格的向后兼容性。因此,仅当您尝试在旧版本(或“企业”发行版)上运行太新的二进制文件时,您才应该遇到麻烦。 。我相信您更容易遇到其他库的问题(C ++在最近的内存中对API / ABI进行了一些更改,其他一些库只是不关心向后兼容性)。
可悲的是,确定的唯一方法就是尝试。
(这与goldilocks的回答基本相同,但对幕后情况进行了更多解释。)
GNU libc的核心共享库libc.so.6
(在Linux上; Hurd具有不同的SONAME)具有非同寻常的属性(对于共享库),您可以将其作为可执行文件调用。如果这样做,它将打印出GNU实用程序通常在运行时会打印的内容--version
,如下所示:
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.2.
Compiled on a Linux 3.12.6 system on 2014-03-02.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
但是,当然,libc.so.6
生活所在的目录不在中$PATH
,因此您必须知道在哪里寻找它。它可能是/lib
,/lib64
,/usr/lib
,或一些更怪的(在这种情况下)。方便地,ldd
将告诉您:
$ ldd /bin/sh | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5660b93000)
为了使它正常工作,您必须知道动态链接的二进制可执行文件的完整路径名。该sh
可执行文件是保证在/bin
(因为这么多的#!
脚本,希望它是),而自身不能是一个#!
脚本。它可能是静态链接的,但多年来我还没有遇到能做到这一点的系统。
如果您使用uClibc或musl或更奇特的工具运行,我不知道该怎么办。
$ ldd $(which sh) | grep libc
。:D