web-dev-qa-db-ja.com

私のシステムはどのCラ​​イブラリバージョンを使用していますか?

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

  • ダウンロードを検討している巨大なソースパッケージがあり、これは適切なチェックを行い、ライブラリの最小バージョンをリストしていると確信していますが、機能するかどうかを最初にチェックすることで、潜在的な手間を省きたいと思います。

  • 私は ABI互換性 について心配しています。システムのパッケージ管理システムの外部にインストールしてみたいサードパーティのバイナリがいくつかあります。

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

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

44
goldilocks

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

正確なバージョンを確認する最も簡単な方法は、Cライブラリに付属しているlddに問い合わせることです。

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

残念ながら、manページにはバージョン番号が記載されていません。 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.
51
goldilocks

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

14
derobert

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

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では機能せず、segfaultします。

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>に関連するGLIBCマクロを定義する<features.h>が含まれます。関数の宣言には<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などのフラグを渡す場合にも機能します。

clibc を使用している場合(OpenWRTなどで使用されます)、__UCLIBC_MAJOR____UCLIBC_MINOR____UCLIBC_SUBLEVEL__、および__UCLIBC__<features.h>で定義しているため、上記のCのマイナーバリエーションを使用して簡単に検出されますコードスニペット。互換性のために、uClibcは上記で使用されているGNU/GLIBCマクロも定義する場合があります。現在、glibc-2.2になりすましています。現在gnu_get_libc_X()関数を実装していませんが、 does getconfを実装していますが、これも誤解を招く可能性があります(getconf GNU_LIBC_VERSIONに対して空の回答が返されると思います) 、私のビルド環境は今日落ち込んでいるので確認できません。)

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

(FWIW、autoconfを使用するソフトウェアで数年以上、checked-for glibc機能よりもunchecked-for gccおよびg++要件で多くの問題がありました。)

10
mr.spuratic

それを取得する別の方法:

getconf GNU_LIBC_VERSION
5
cuonglm

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

悲しいことに、確実に知る唯一の方法は試すことです。

5
vonbrand

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

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にあることが保証されており(多くの#!スクリプトが想定しているため)、それ自体を#!スクリプトにすることはできません。 couldは静的にリンクされていますが、長年にわたってそのようなシステムに遭遇したことはありません。

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

5
zwol