システムで使用しているCライブラリのバージョンは何ですか?


43

システムが使用しているユーザーランドCライブラリを確認するにはどうすればよいですか?この情報を必要とする考えられる理由は次のとおりです。

  • ダウンロードを検討している巨大なソースパッケージがあり、適切なチェックを行い、最小ライブラリバージョンをリストしますが、動作するかどうかを最初にチェックすることで、面倒な作業を省くことができます。

  • システムのパッケージ管理システムの外部で試してインストールしたいサードパーティのバイナリとABIの互換性が心配です。

  • 私のシステムのライブラリの最小バージョンの必要性について言及しているドキュメントのソースパッケージがありますが、ビルドプロセスはチェックを実行しません。

  • 特定のシステムをターゲットとするクロスコンパイラを構築していますが、前方互換性の問題を危険にさらしたくないです。


ぜひ試してみてください。バージョンがすべてを伝えているかどうかはわかりません。パッチはどうですか?または、分布はABIの変更に注意していますか?エクスポートされたシンボルが解決されるかどうかは問題ではありませんか?
ファヒムミタ14

いい答えですが、Macでこれを行う方法については誰も言及していませんlddotool --version同じ情報を提供しているとみなせるかどうかはわかりません。
dubiousjim

@dubiousjim誰かができました。Macユーザーではないからです。ここについては、特にそれについて尋ねる必要があるかもしれません-問題の一部は、おそらく人々がOSXで普通のCをあまり使わないのでしょうか?しかし、私は知っている常連がいると確信しています。チャットでこれへのリンクを投稿して何が起こるかを確認することもできますが、おそらく新しい、より具体的な質問の方が良いでしょう。
goldilocks

回答:


50

GNU / Linuxシステムは通常、glibc(Fedora / Redhatファミリー、Arch)またはその親類であるeglibc(Debian / Ubuntuファミリー)を使用します。eglibcは現在glibcにマージされているため(「News」の下に作成されたEGLIBC 2.19 Branchを参照)、近い将来それらはすべてglibcになります。

正確なバージョンを確認する最も簡単な方法はldd、Cライブラリに付属のask を使用することです。

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 3行目にあります。

> /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.

GNU / Linuxシステムを「通常」にするものは何ですか?muslを使用した配布はどうですか?
エリオットフリッシュ

1
@ElliottFrisch(ある、私は確信している)システムがあるかもしれないので、それは、「通常のGNU / Linuxの」(形容詞、名詞)、のように、GNU / Linuxへ適用することを意図していない(E)はglibcが、使用致します GNUスタックの残り(bash、binutilsなど)を使用します。これらの「異常な」GNU / Linuxシステムを検討します。しかし、「通常」を削除し、「GNU / Linuxシステムが通常使用する...」に変更しました。注:私は意図的に質問を WRT OSの仕様を開いたままにしました(LinuxまたはGNUまたはglibcタグはありません)。したがって、U&Lに適したシステムに関する回答を追加する場合は、行ってください。
goldilocks

1
あなたが示したようにそれを見つけてバージョンを問い合わせた後、利用可能な拡張機能も印刷しました!(私の場合はスタブ、crypt、libidn、ネイティブスレッド、バインド)、ABI:libc ABI:UNIQUE IFUNCを参照します。

Debianは/lib/`uname -m`*パスを使用します。ポータブルな方法は次のようになりますfind /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version。良い説明をありがとう。
ペビック

@pevik:間違った、腕それの/lib/arm-linux-gnueabihf/libc.so.6、およびない/lib/armv7l/libc.so.6に
困惑

14

システムは実際には1つのCライブラリに限定されません。ただし、ほとんどの場合、主に1つだけを使用します。これは、デフォルトのコンパイラでも使用されます。そして、コンパイルするためにソースコードをダウンロードしているので、それがあなたが心配しているものです。

簡単なプログラムから始めます。

#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-shlibdepsobjdump、ビルド中にバイナリのDebianパッケージに必要な依存関係の最小バージョンを決定するために、Debianライブラリパッケージに格納されているシンボル情報とともに内部で使用します。基本的に、バイナリDebianパッケージによってエクスポートされたシンボルを調べ、それらのシンボルを含むライブラリの最小バージョンを見つけます。


9

最も包括的なものではありませんが、明らかな答えは、パッケージマネージャーを確認することです。

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が何をしようとしているのかを正確に伝える1つの簡単な方法は、コンパイルです:

#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を(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は、今日sulkingされ、。)

まれにdietlibcを使用している場合、実行diet -vするとバージョンが表示されます。

(FWIWは、ソフトウェア使用したautoconfと、数年にわたって、私はのために、未チェックでより多くの問題がありましたgccし、g++チェックインのためにglibcの機能を備えたよりも要件を。)


5

GNU libc(ほとんどのLinuxディストリビューションがいずれかの形式で使用するもの)は、厳密な後方互換性を保つために非常に長くなります。したがって、古いバージョン(または「エンタープライズ」ディストリビューション、通常はバージョン、特にCライブラリなどの基本バージョンをフリーズし、厳密なバイナリ互換性を維持しながら修正をバックポートする)で新しいバイナリを実行しようとする場合にのみ、トラブルに遭遇するはずです。他のライブラリで問題が発生する可能性がはるかに高いと思います(C ++には最近のメモリでAPI / ABIの変更がいくつかありましたが、他の一部のライブラリは後方互換性を気にしません)。

残念ながら、確実に見つける唯一の方法は試してみることです。


+1実際には、下位互換性に関するチャートがあり、すべてが100%であるわけではない唯一の理由は、難解なGNU拡張機能を悪用するコードによるものだと思います。ただし、前方互換性に関して私が知っているようなグラフはありません。これは、あなたがより重要な関心事であることに注意してください。
goldilocks 14年

5

(これは本質的にゴルディロックスの答えと同じですが、内部で何が起こっているかについてのもう少しの説明があります。)

GNU libcのコア共有ライブラリlibc.so.6(Linuxの場合、Hurdには異なるSONAMEがあります)には、実行可能ファイルとして呼び出すことができる異常なプロパティ(共有ライブラリ用)があります。実行すると--version、次のように、GNUユーティリティがで実行されたときに通常印刷されるようなものが出力されます。

$ /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.6livesが存在するディレクトリはにない$PATHので、どこを探すべきかを知る必要があります。それはであるかもしれない/lib/lib64/usr/lib、または(この場合のように)さえwackier何か。便利に、lddあなたに教えます:

$ ldd /bin/sh | grep libc
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5660b93000)

もちろん、それが機能するためには、動的にリンクされたバイナリ実行可能ファイルのフルパス名を知っている必要があります。sh実行可能ファイルがであることが保証されている/bin(ように多くのため#!のスクリプトは、それがあることを期待)、そして自身がすることはできません#!スクリプト。静的にリンクすることもできますが、これを長年行ってきたシステムには遭遇していません。

uClibcやmusl、またはもっとエキゾチックなもので実行している場合、何をするのかわかりません。


2
さて、あなたはしていない持っているに/ binに/ shまたは何でも完全なパスを知っています。いつでもできます$ ldd $(which sh) | grep libc。:D
マットノルドホフ14年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.