Welche C-Bibliotheksversion verwendet mein System?

43

Wie kann ich sicher sagen, welche userland C-Bibliothek mein System verwendet? Mögliche Gründe für die Verwendung dieser Informationen sind:

  • Es gibt ein gigantisches Quellcode-Paket, das ich herunterladen möchte. Ich bin sicher, dass es ordnungsgemäße Überprüfungen durchführt und eine Mini-Bibliotheksversion auflistet.

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

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

  • Ich erstelle einen Cross-Compiler für ein bestimmtes System und möchte keine Probleme mit der Vorwärtskompatibilität riskieren .

Goldlöckchen
quelle
Warum nicht versuchen und sehen. Ich weiß nicht, ob die Version Ihnen alles sagt; Was ist mit Patches? Oder ist bei der Änderung des ABI Vorsicht geboten? Ist es nicht ein Problem, ob die exportierten Symbole aufgelöst sind oder so?
Faheem Mitha
Nette Antworten, aber niemand spricht an, wie man das auf einem Mac macht, wo es keine gibt ldd. Ich bin mir nicht sicher, ob otool --versiondies als die gleiche Information angesehen werden kann.
dubiousjim
@dubiousjim Jemand könnte; Nur nicht ich, weil ich kein Mac-Benutzer bin. Möglicherweise müssen Sie hier speziell nachfragen - ein Teil des Problems besteht darin, dass die Leute unter OSX im Allgemeinen nicht viel C verwenden. Aber ich bin sicher, es wird einen Stammspieler geben, der es weiß. Sie können auch einen Link dazu im Chat posten und sehen, was passiert, aber wahrscheinlich ist eine neue, spezifischere Frage besser.
Goldlöckchen

Antworten:

50

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

Am einfachsten können Sie die genaue Version überprüfen, indem Sie fragen ldd, welche Version 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 nicht sicher sind ldd, 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 es gibt einen Hinweis darauf, wo es zu finden ist.

> $(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, weil die C-Bibliothek sich nicht irgendwo aufhalten muss, whereisum sie zu finden.

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

Leider enthält die Manpage keine Versionsnummer. lddEs ist immer noch praktisch, 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 ist 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.
Goldlöckchen
quelle
Was macht ein GNU / Linux-System "normal"? Was ist mit Distributionen mit musl ?
Elliott Frisch
1
@ElliottFrisch Es sollte für GNU / Linux gelten, wie in "normales GNU / Linux" (Adjektiv, Substantiv), da es Systeme geben könnte (bin ich mir sicher), die (e) glibc nicht verwenden, aber tun Verwenden Sie den Rest des GNU-Stacks (bash, binutils usw.). Ich würde diese "ungewöhnlichen" GNU / Linux-Systeme in Betracht ziehen. Aber ich habe das "normale" entfernt und es in "GNU / Linux-Systeme verwenden normalerweise ..." geändert . Hinweis: Ich habe die Frage absichtlich offen gelassen (es gibt kein Linux-, GNU- oder glibc-Tag). Wenn Sie also eine Antwort zu einem für U & L geeigneten System hinzufügen möchten, tun Sie dies bitte.
Goldlöckchen
1
Nachdem ich es gefunden habe, wie Sie es gezeigt haben und die Version abgefragt habe, wurden auch die verfügbaren Erweiterungen gedruckt! (in meinem Fall Stubs, Crypt, Libidn, native Threads und Bind) und verwiesen auf ABI: libc ABIs: UNIQUE IFUNC.
Debian benutzt /lib/`uname -m`*path. So tragbare Art und Weise wäre: find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version. Danke für die nette Erklärung.
Pevik
@pevik: Falsch, auf dem Arm ist es /lib/arm-linux-gnueabihf/libc.so.6 und nicht /lib/armv7l/libc.so.6
Quandary
14

Ein System ist nicht auf eine C-Bibliothek beschränkt. Die meisten verwenden jedoch in erster Linie nur einen, der auch vom Standard-Compiler verwendet wird. Und da Sie Quellcode zum Kompilieren herunterladen, ist dies derjenige, um den Sie sich kümmern.

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 ermitteln Sie dann ldd, 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.6oder 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 objdump -p /lib/x86_64-linux-gnu/libc.so.6im Abschnitt mit den Versionsdefinitionen nachsehen , ob Sie Hinweise darauf 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 in der Tat 2.18 ist. Es ist jedoch eglibc (es soll mit glibc 2.18 binär kompatibel sein, daher werden die gleichen Symbolversionen verwendet).

Sie könnten auch versuchen strings, etwas darüber herauszufinden. Sie möchten eine längere minimale Lä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 diese eglibc.

HINWEIS: Das Debian-Paket-Dienstprogramm dpkg-shlibdepsverwendet objdumpunter der Haube zusammen mit den in Debian-Bibliothekspaketen gespeicherten Symbolinformationen, um die Mindestversionen von Abhängigkeiten zu bestimmen, die von binären Debian-Paketen zum Zeitpunkt der Erstellung benötigt werden. Im Grunde betrachtet es die vom Debian-Binärpaket exportierten Symbole und findet dann die Mindestversionen der Bibliotheken, die diese Symbole enthalten.

derobert
quelle
9

Die naheliegende, wenn auch nicht die umfassendste Antwort ist die Überprüfung Ihres Paketmanagers, z

rpm -qi glibc
dpkg -l libc6

(Leider hat glibc keine pkconfig- .pcDatei, pkgconfig --modversion glibcist also kein Runner.) Siehe auch @ Gnoucs exzellenter getconfVorschlag.

Der einfachste Fall mit gcc + glibc und der, den ich meistens zuerst benutze, ist, einfach auszuführen libc.so, wie in einigen anderen Antworten hier beschrieben. Es müssen keine Argumente übergeben werden, die Version wird standardmäßig ausgegeben. Dies funktioniert bis zu glibc-2.1 (glibc-2.0-seg-Fehler), obwohl Sie vor langer Zeit das (inzwischen zurückgezogene) glibcbugSkript ü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, erst 1.0 waren). Es funktioniert nicht mit uClibc, es segfaults.

Eine einfache Möglichkeit, genau zu sagen, was Sie gcctun werden, 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, <stdio.h>enthält , <features.h>welche die entsprechenden GLIBC Makros definiert, müssen Sie <gnu/libc-version.h>für die Funktionsdeklarationen.)

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 Sie verwenden glibc (oder eglibc) , dann ldwird auch die Version bestätigen (sorry, das ist nicht richtig).

Wenn __GNU_LIBRARY__es nicht definiert ist, werden Sie Fehler bekommen, dann ist es Zeit für Plan B.

gcc -dumpmachinekann helfen, zB für Uclibc hat es ein -uclibcSuffix, wie kann gcc -dumpspecs | grep dynamic-linker. Dies kann auch die ABI implizieren.

gcc -print-file-name=libc.sowird Ihnen sagen, welche Datei der Compiler für " -lc" verwenden wird. Dies ist mit ziemlicher Sicherheit ein Linker-Skript in Ihrer gcc-Installation, das Sie als Klartext lesen können. Das zeigt den genauen Pfad zu libc.so. Dies funktioniert auch, wenn Sie Flags wie -m32oder übergeben -m64.

Für den Fall , verwenden Sie uclibc ( und wurden von OpenWRT und mehr), es definiert __UCLIBC_MAJOR__, __UCLIBC_MINOR__und __UCLIBC_SUBLEVEL__als auch __UCLIBC__in <features.h>, so dass es leicht ist erkannt eine kleinere Variante des obigen C - Code - Snippet verwenden. Im Interesse der Kompatibilität kann uClibc auch die oben verwendeten GNU / GLIBC-Makros definieren, die derzeit als glibc-2.2 bezeichnet werden. Dabei spielt es keine derzeit die Umsetzung gnu_get_libc_X()Funktionen, aber es nicht implementieren , getconfdie auch die Irre führen kann (ich vermute , es gibt eine leere Antwort getconf GNU_LIBC_VERSION, mein Build env schmollt heute so kann ich nicht bestätigen.)

In dem unwahrscheinlichen Fall, dass Sie dietlibc verwenden , wird beim Ausführen diet -vdie Version angezeigt.

(FWIW, über mehrere Jahre hinweg hatte ich mit Software, die Autoconf verwendet, mehr Probleme mit ungeprüften Funktionen gccund g++Anforderungen als mit auf glibc geprüften Funktionen.)

mr.spuratic
quelle
5

GNU libc (was die meisten Linux-Distributionen in der einen oder anderen Form verwenden) ist sehr bemüht, um eine strikte Abwärtskompatibilität zu gewährleisten. Daher sollten Sie nur dann auf Probleme stoßen, wenn Sie versuchen, eine zu neue Binärdatei auf einer alten Version auszuführen (oder auf einer "Enterprise" -Distribution, die normalerweise Versionen einfriert, insbesondere Basisversionen wie die C-Bibliothek, Backporting-Fixes und strenge Binärkompatibilität). . 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 kümmern sich einfach nicht um die Abwärtskompatibilität).

Leider ist der einzige Weg, um sicher herauszufinden, zu versuchen.

vonbrand
quelle
+1 Tatsächlich haben sie eine Tabelle zur Abwärtskompatibilität und ich würde annehmen, dass der einzige Grund, warum nicht alles 100% ist, der Code ist, der esoterische GNU-Erweiterungen ausnutzt. Es gibt jedoch kein solches Diagramm, das mir in Bezug auf die Vorwärtskompatibilität bekannt ist , was, wie Sie bemerken, eher die eigentliche Sorge ist.
Goldlöckchen
5

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

Die gemeinsam libc.so.6genutzte Kernbibliothek für GNU libc (unter Linux; Hurd hat einen anderen SONAME) hat die ungewöhnliche Eigenschaft (für gemeinsam genutzte Bibliotheken), dass Sie sie als ausführbare Datei aufrufen können. Wenn Sie dies tun, wird die Art von Dingen gedruckt, die GNU-Dienstprogramme normalerweise drucken, wenn sie mit ausgeführt --versionwerden:

$ /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 ist das Verzeichnis, in dem sich das libc.so.6Leben befindet, nicht vorhanden. $PATHSie müssen also wissen, wo Sie danach suchen müssen. Es könnte sein , in /lib, /lib64, /usr/liboder etwas noch wackier (wie in diesem Fall). Günstigerweise lddwerden Sie 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 shausführbare Datei befindet sich garantiert in /bin(da dies von so vielen #!Skripten erwartet wird) 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 tat.

Ich weiß nicht, was du machst, wenn du mit uClibc oder Musl oder etwas Exotischerem unterwegs bist.

zwol
quelle
2
Nun, Sie nicht haben , um den vollständigen Pfad kennen zu / bin / sh oder was auch immer. Sie können immer $ ldd $(which sh) | grep libc. : D
Matt Nordhoff
5

Ein anderer Weg, um es zu bekommen:

getconf GNU_LIBC_VERSION
cuonglm
quelle
Nizza, sollte dies zuverlässig funktionieren, da glibc-2.3.3.
mr.spuratic