it-swarm.com.de

Welche C-Bibliotheksversion verwendet mein System?

Wie kann ich sicher feststellen, welche Userland C-Bibliothek mein System verwendet? Mögliche Gründe, diese Informationen zu benötigen, sind:

  • Es gibt ein gigantisches Quellpaket, das ich herunterladen möchte. Ich bin sicher, dass es ordnungsgemäße Überprüfungen durchführt und eine Mininum-Bibliotheksversion auflistet, aber ich würde mir lieber einen potenziellen Ärger ersparen, indem ich zuerst überprüfe, ob es funktioniert.

  • Ich bin besorgt über ABI-Kompatibilität mit einigen Binärdateien von Drittanbietern, die ich außerhalb des Paketverwaltungssystems des Systems installieren möchte.

  • Ich habe ein Quellpaket, in dessen Dokumentation die Notwendigkeit einer Mindestversion der Bibliothek meines Systems erwähnt wird, aber der Erstellungsprozess führt keine Überprüfungen durch.

  • Ich baue einen Cross-Compiler, der auf ein bestimmtes System abzielt, und möchte keine Vorwärtskompatibilität Probleme riskieren.

44
goldilocks

GNU/Linux-Systeme verwenden normalerweise entweder glibc (Fedora/Redhat-Familie, Arch) oder seinen engen Cousin eglibc (Debian/Ubuntu-Familie); da eglibc nun wieder in glibc zusammengeführt wird ( siehe EGLIBC 2.19 Branch Created unter "News" ), werden sie in naher Zukunft alle wieder glibc sein.

Der einfachste Weg, die genaue Version zu überprüfen, besteht darin, ldd zu fragen, das mit der C-Bibliothek geliefert wird.

Auf Fedora 20:

> ldd --version
ldd (GNU libc) 2.18

Das ist glibc 2.18.

Auf Raspbian (Debian 7-Port für ARMv6 Broadcom SoC):

> ldd --version
ldd (Debian EGLIBC 2.13-38+rpi2) 2.13

Das ist eglibc 2.13.

Wenn Sie aus irgendeinem Grund einige Teile gemischt und abgeglichen haben oder sich bei ldd nicht sicher sind, können Sie die C-Bibliothek direkt abfragen.

> whereis libc.so
libc: /usr/lib64/libc.a /usr/lib64/libc.so /usr/share/man/man7/libc.7.gz

Keines davon ist ausführbar, aber sie geben einen Hinweis darauf, wo man eines findet.

> $(find /usr/lib64/ -executable -name "*libc.so*") --version
GNU C Library (GNU libc) stable release version 2.18, by Roland McGrath et al.

Es ist jedoch nicht unbedingt so einfach, da sich die C-Bibliothek nicht irgendwo befinden muss, wo whereis sie finden kann.

> whereis libc.so
libc: /usr/share/man/man7/libc.7.gz

Leider enthält die Manpage keine Versionsnummer. ldd ist immer noch nützlich, da jede funktionierende, dynamisch verknüpfte ausführbare Datei auf dem System (z. B. fast alles in /usr/bin) mit der C-Bibliothek verknüpft wird.

> 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 Steht in der dritten Zeile.

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

Ein System ist nicht auf eine C-Bibliothek beschränkt. Die meisten verwenden jedoch hauptsächlich nur eine, die auch vom Standard-Compiler verwendet wird. Und da Sie zum Kompilieren Quellcode herunterladen, geht es Ihnen darum.

Beginnen Sie mit einem einfachen Programm:

#include <stdio.h>
int main() {
    printf("Hello, world\n");
    return 0;
}

kompilieren Sie es mit dem Compiler, den Sie für den Quellcode verwenden möchten, und verwenden Sie dann ldd, um herauszufinden, wo sich die C-Bibliothek befindet:

$ 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)

Sie haben jetzt den Pfad zur C-Bibliothek. Sie können dies in Ihrem Paketmanager nachschlagen, um das Paket zu finden (z. B. dpkg -S /lib/x86_64-linux-gnu/libc.so.6 Oder rpm -q -f /lib/x86_64-linux-gnu/libc.so.6).

Zumindest im Fall von eglibc/glibc können Sie es ausführen:

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

Schließlich können Sie im Abschnitt Versionsdefinitionen nachsehen, ob Sie Hinweise von objdump -p /lib/x86_64-linux-gnu/libc.so.6 Erhalten können:

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 

Beachten Sie, dass das GLIBC_2.18-Symbol die neueste Versionsnummer unter den aufgelisteten Symbolen hat und die Bibliotheksversion tatsächlich 2.18 ist. Es ist jedoch eglibc (es soll binär kompatibel mit glibc 2.18 sein, daher werden dieselben Symbolversionen verwendet).

Sie können auch versuchen, strings zu verwenden, um etwas darüber herauszufinden. Sie möchten eine längere Mindestlänge angeben (-n) Oder mit grep nach etwas suchen:

$ 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'

beide arbeiten für diesen eglibc.

HINWEIS: Das Debian-Paketdienstprogramm dpkg-shlibdeps Verwendet objdump unter der Haube zusammen mit gespeicherten Symbolinformationen in Debian-Bibliothekspaketen, um die Mindestversionen von Abhängigkeiten zu bestimmen, die von binären Debian-Paketen zur Erstellungszeit benötigt werden. Grundsätzlich werden die vom binären Debian-Paket exportierten Symbole betrachtet und dann die Mindestversionen der Bibliotheken gefunden, die diese Symbole enthalten.

14
derobert

Die offensichtliche Antwort, obwohl nicht die umfassendste, besteht darin, Ihren Paketmanager zu überprüfen, z

rpm -qi glibc
dpkg -l libc6

(Leider hat glibc keine pkconfig .pc - Datei, daher ist pkgconfig --modversion glibc Kein Läufer.) Siehe auch @ Gnoucs ausgezeichneter getconf Vorschlag.

Der einfachste Fall mit gcc + glibc und der, den ich meistens zuerst benutze, besteht darin, einfach libc.so Auszuführen, wie in einigen der anderen Antworten hier beschrieben. Es müssen keine Argumente übergeben werden, es gibt standardmäßig seine Version aus. Dies funktioniert bis zu glibc-2.1 (glibc-2.0-Seg-Fehler, obwohl Sie vor langer Zeit das Skript (jetzt im Ruhestand) glibcbug überprüfen konnten, um die Version zu bestätigen). Diese Methode funktioniert auch mit neueren (> 0.9.15) Versionen von musl-libc (die heute, am 20. März, auf 1.0 gingen). Es funktioniert nicht mit uClibc, es segfaults.

Eine einfache Möglichkeit, genau zu sagen, was Ihr gcc tun wird, ist das Kompilieren:

#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;
}

(Mit glibc enthält <stdio.h><features.h>, das die relevanten GLIBC-Makros definiert. Für die Funktionsdeklarationen benötigen Sie <gnu/libc-version.h>.)

Dies erfasst komplexere Fälle (mehrere Bibliotheken und/oder mehrere Compiler), vorausgesetzt, Sie verwenden natürlich den richtigen Compiler (und die richtigen Flags). (Ich vermute, es wird jedoch nicht zwischen Eglibc und Glibc unterscheiden.)

Wenn Sie sicher sind, dass Sie glibc (oder eglibc) verwenden, bestätigt ld auch die Version (Entschuldigung, das ist nicht korrekt).

Wenn __GNU_LIBRARY__ Nicht definiert ist, werden Fehler angezeigt. Dann ist es Zeit für Plan B.

gcc -dumpmachine Kann helfen, z. für uclibc hat es das Suffix -uclibc, ebenso wie gcc -dumpspecs | grep dynamic-linker. Dies kann auch den ABI implizieren.

gcc -print-file-name=libc.so Sagt Ihnen, welche Datei der Compiler für "-lc" Verwendet. Dies ist mit ziemlicher Sicherheit ein Linker-Skript in Ihrer gcc-Installation, das Sie als einfachen Text lesen können. Das zeigt den genauen Pfad zu libc.so. Dies funktioniert auch, wenn Sie Flags wie -m32 Oder -m64 Übergeben.

Für den Fall, dass Sie clibc verwenden (wie von OpenWRT und anderen verwendet), werden __UCLIBC_MAJOR__, __UCLIBC_MINOR__ Und __UCLIBC_SUBLEVEL__ Sowie __UCLIBC__ In <features.h>, So dass es leicht mit einer geringfügigen Variation des obigen C-Code-Snippets erkannt werden kann. Im Interesse der Kompatibilität kann uClibc auch die oben verwendeten GNU/GLIBC-Makros definieren. Derzeit gibt es vor, glibc-2.2 zu sein. Es implementiert derzeit nicht die Funktionen gnu_get_libc_X(), aber es implementiert getconf, was ebenfalls irreführend sein kann (ich vermute es gibt eine leere Antwort für getconf GNU_LIBC_VERSION zurück, meine Build-Umgebung schmollt heute, daher kann ich nicht bestätigen.)

In dem unwahrscheinlichen Fall, dass Sie dietlibc verwenden, wird durch Ausführen von diet -v Die Version angezeigt.

(FWIW, über mehrere Jahre hinweg hatte ich mit Software, die Autoconf verwendet, mehr Probleme mit nicht aktivierten gcc - und g++ - Anforderungen als mit aktivierten glibc-Funktionen.)

10
mr.spuratic

Ein anderer Weg, um es zu bekommen:

getconf GNU_LIBC_VERSION
5
cuonglm

GNU libc (was die meisten Linux-Distributionen in der einen oder anderen Form verwenden) unternimmt große Anstrengungen, um eine strikte Abwärtskompatibilität zu gewährleisten. Sie sollten also nur dann in Schwierigkeiten geraten, wenn Sie versuchen, eine zu neue Binärdatei auf einer alten Version auszuführen (oder auf einer "Enterprise" -Distribution, die normalerweise Versionen einfriert, insbesondere grundlegende Versionen wie die C-Bibliothek, die Korrekturen zurückportieren und dabei die riguröse Binärkompatibilität beibehalten). . Ich glaube, dass Sie viel häufiger auf Probleme mit anderen Bibliotheken stoßen (C++ hatte einige API/ABI-Änderungen im letzten Speicher, einige andere Bibliotheken nur nicht auf Abwärtskompatibilität achten).

Leider ist der einzige Weg, dies sicher herauszufinden, es zu versuchen.

5
vonbrand

(Dies ist im Wesentlichen das Gleiche wie die Antwort von Goldlöckchen, jedoch mit einer weiteren Erklärung dessen, was unter der Haube vor sich geht.)

Die gemeinsam genutzte Kernbibliothek für GNU libc, libc.so.6 (Unter Linux; Hurd hat einen anderen SONAME) hat die ungewöhnliche Eigenschaft (für gemeinsam genutzte Bibliotheken), dass Sie sie als aufrufen können Wenn Sie dies tun, wird Folgendes ausgegeben: GNU Dienstprogramme werden normalerweise gedruckt, wenn sie mit --version ausgeführt werden, wie folgt:

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

Aber natürlich befindet sich das Verzeichnis, in dem libc.so.6 Lebt, nicht in $PATH, Daher müssen Sie wissen, wo Sie danach suchen müssen. Es könnte in /lib, /lib64, /usr/lib Oder etwas noch Verrückterem sein (wie in diesem Fall). Praktischerweise wird ldd Ihnen sagen:

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

Damit dies funktioniert, müssen Sie natürlich den vollständigen Pfadnamen einer dynamisch verknüpften ausführbaren Binärdatei kennen. Die ausführbare Datei sh befindet sich garantiert in /bin (Weil so viele #! - Skripte dies erwarten) und kann selbst kein #! - Skript sein . Es könnte statisch verknüpft sein, aber ich bin seit vielen Jahren nicht mehr auf ein System gestoßen, das dies getan hat.

Ich weiß nicht, was du machst, wenn du mit uClibc oder musl oder etwas Exotischerem rennst.

5
zwol