Quale versione della libreria C utilizza il mio sistema?


43

Come posso sapere con certezza quale libreria C userland viene utilizzata dal mio sistema? I possibili motivi per richiedere queste informazioni includono:

  • C'è un gigantesco pacchetto sorgente che sto prendendo in considerazione per il download, che sono sicuro che farà i controlli corretti ed elenca una versione di libreria mininum, ma preferirei risparmiarmi una potenziale seccatura controllando prima se funzionerà.

  • Sono preoccupato per la compatibilità ABI con alcuni file binari di terze parti che voglio provare a installare al di fuori del sistema di gestione dei pacchetti del sistema.

  • Ho un pacchetto sorgente la cui documentazione menziona la necessità di una versione minima della libreria del mio sistema, ma il processo di compilazione non esegue alcun controllo.

  • Sto costruendo un compilatore multiplo destinato a un sistema specifico e non voglio rischiare problemi di compatibilità .


Perché non provarlo e vedere. Non so se la versione ti dice tutto; che dire delle patch? Oppure le distrazioni sono attente a modificare l'ABI? Non è il problema se i simboli esportati sono stati risolti o qualcosa del genere?
Faheem Mitha,

Belle risposte, ma nessuno si rivolge a come farlo su un Mac, dove non c'è ldd. Non sono sicuro che si otool --versionpossa ritenere che stiano fornendo le stesse informazioni.
dubiousjim,

@dubiousjim Qualcuno potrebbe; proprio non io, perché non sono un utente Mac. Da queste parti potresti doverti chiedere in particolare - una parte del problema è che le persone generalmente non usano molto C in OSX? Ma sono sicuro che ci sarà un normale che lo sa. Puoi anche pubblicare un link a questo in chat e vedere cosa succede, ma probabilmente una nuova domanda più specifica sarebbe meglio.
Riccioli d'oro,

Risposte:


50

I sistemi GNU / Linux di solito usano glibc (famiglia Fedora / Redhat, Arch) o suo cugino stretto, eglibc (famiglia Debian / Ubuntu); dal momento che eglibc è stato nuovamente riunito in glibc ( vedi la sezione EGLIBC 2.19 creata sotto "Notizie" ), nel prossimo futuro saranno tutti di nuovo glibc.

Il modo più semplice per verificare la versione esatta è chiedere ldd, fornito con la libreria C.

Su Fedora 20:

> ldd --version
ldd (GNU libc) 2.18

Questo è glibc 2.18.

Su Raspbian (porta Debian 7 per SoC Broadcom ARMv6):

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

Questo è eglibc 2.13.

Se per qualsiasi motivo hai mescolato e abbinato alcune parti o altrimenti non sei sicuro ldd, puoi interrogare direttamente la libreria C.

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

Nessuno di questi è eseguibile ma forniscono un indizio su dove trovarne uno.

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

Tuttavia, non è necessariamente così facile, perché la libreria C non deve risiedere da qualche parte per whereistrovarla.

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

Sfortunatamente, la pagina man non fornisce un numero di versione. lddè ancora utile, poiché qualsiasi eseguibile funzionante, collegato dinamicamente al sistema (ad esempio, quasi tutto in /usr/bin) si collegherà alla libreria 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 è sulla terza linea.

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

Cosa rende "normale" un sistema GNU / Linux? Che dire delle distribuzioni che usano il musl ?
Elliott Frisch

1
@ElliottFrisch Si intendeva applicare a GNU / Linux, come in "normale GNU / Linux" (aggettivo, sostantivo), dal momento che potrebbero esserci (sono, ne sono sicuro) sistemi che non usano (e) glibc ma lo fanno usa il resto dello stack GNU (bash, binutils, ecc.). Vorrei considerare quei sistemi GNU / Linux "insoliti". Ma ho rimosso il "normale" e l'ho cambiato in "I sistemi GNU / Linux di solito usano ...". Nota: ho lasciato intenzionalmente aperte le domande specifiche del sistema operativo WRT (non esiste alcun tag Linux o GNU o glibc), quindi se si desidera aggiungere una risposta relativa a qualsiasi sistema appropriato a U&L, si prega di farlo.
Riccioli d'oro

1
Dopo averlo trovato come hai mostrato e ho cercato la versione, ha anche stampato le estensioni disponibili! (nel mio caso stub, crypt, libidn, thread nativi e bind) e riferiti ad ABI: libc ABI: UNIQUE IFUNC.

Debian usa il /lib/`uname -m`*percorso. Così modo portatile potrebbe essere: find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version. Grazie per la bella spiegazione.
pevik,

@pevik: Sbagliato, a braccio è /lib/arm-linux-gnueabihf/libc.so.6, e non /lib/armv7l/libc.so.6
Quandary

14

Un sistema non è in realtà limitato a una libreria C. La maggior parte, tuttavia, ne utilizza principalmente solo una, che sarà anche quella utilizzata dal compilatore predefinito. E dal momento che stai scaricando il codice sorgente da compilare, questo è quello che ti interessa.

Inizia con un programma banale:

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

compilalo usando il compilatore che intendi utilizzare per il codice sorgente, quindi usa lddper scoprire dove si trova la libreria 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)

Ora hai il percorso per la libreria C. Puoi cercarlo nel gestore dei pacchetti per trovare il pacchetto (ad esempio, dpkg -S /lib/x86_64-linux-gnu/libc.so.6o rpm -q -f /lib/x86_64-linux-gnu/libc.so.6).

Almeno nel caso di eglibc / glibc, puoi eseguirlo:

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

Infine, puoi vedere se riesci a ottenere indizi da objdump -p /lib/x86_64-linux-gnu/libc.so.6, guardando nella sezione delle definizioni della versione :

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 

Nota come il simbolo GLIBC_2.18 abbia il numero di versione più recente tra i simboli elencati e la versione della libreria sia effettivamente 2.18. È peròbc (mira a essere binario compatibile con glibc 2.18, quindi utilizza le stesse versioni di simboli).

Potresti anche tentare di utilizzare stringsper scoprire qualcosa al riguardo. Ti consigliamo di specificare una lunghezza minima più lunga ( -n) o utilizzare grep per cercare qualcosa:

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

entrambi lavorano per questo eglibc.

NOTA: L'utilità del pacchetto Debian dpkg-shlibdepsusa objdumpsotto il cofano, insieme alle informazioni sui simboli memorizzate nei pacchetti della libreria Debian per determinare le versioni minime delle dipendenze richieste dai pacchetti binari Debian al momento della compilazione. Fondamentalmente, esamina i simboli esportati dal pacchetto binario Debian e quindi trova le versioni minime delle librerie che contengono quei simboli.


9

La risposta ovvia, sebbene non la più completa, è controllare il gestore dei pacchetti, ad es

rpm -qi glibc
dpkg -l libc6

(Purtroppo, glibc non ha un .pcfile pkconfig , quindi pkgconfig --modversion glibcè un non-runner.) Vedi anche l'eccellente getconfsuggerimento di @ Gnouc .

Il caso più semplice, con gcc + glibc, e quello che uso principalmente per primo è quello di eseguire libc.so, come indicato in alcune delle altre risposte qui. Non è necessario passare alcun argomento, per impostazione predefinita restituisce la sua versione. Questo funziona fino a glibc-2.1 (glibc-2.0 seg-faults, anche se fino a quel momento si poteva controllare lo glibcbugscript (ora ritirato) per confermare la versione). Questo metodo funziona anche con le versioni recenti (> 0.9.15) di musl-libc (che è appena arrivato 1.0 oggi, 20 marzo). Non funziona con uClibc, segfaults.

Un modo semplice per dire esattamente cosa gccstai per fare è compilare:

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

(con glibc, <stdio.h>include <features.h>quale definisce le macro GLIBC pertinenti, è necessario <gnu/libc-version.h>per le dichiarazioni di funzione.)

Questo cattura casi più complessi (più libc e / o più compilatori), supponendo che tu stia usando il compilatore giusto (e flag) ovviamente. (Ho il sospetto che non distinguerà tra eglibc e glibc proprio.)

Se sei sicuro di usare glibc (o eglibc) ld, confermerai anche la versione (scusa, non è corretto).

Se __GNU_LIBRARY__non viene definito, verranno visualizzati errori, quindi è il momento del piano B.

gcc -dumpmachinepuò aiutare, ad es. per uclibc ha un -uclibcsuffisso, come può gcc -dumpspecs | grep dynamic-linker. Ciò può anche implicare l'ABI.

gcc -print-file-name=libc.soti dirà quale file utilizzerà il compilatore " -lc", questo è quasi certamente uno script linker all'interno della tua installazione di gcc, che puoi leggere come testo semplice. Ciò mostrerà il percorso esatto per libc.so. Questo funzionerà anche se stai passando bandiere come -m32o -m64.

Nel caso in cui si utilizzi uclibc (usati per OpenWRT e più), definisce __UCLIBC_MAJOR__, __UCLIBC_MINOR__e __UCLIBC_SUBLEVEL__così come __UCLIBC__in <features.h>, quindi è facilmente rilevabile mediante una variazione minore di quanto sopra C frammento di codice. Nell'interesse della compatibilità, uClibc può anche definire le macro GNU / GLIBC come usate sopra, attualmente finge di essere glibc-2.2. E 'attualmente non implementare le gnu_get_libc_X()funzioni, ma non implementare getconfche possono anche trarre in inganno (ho il sospetto che restituisce una risposta vuota per getconf GNU_LIBC_VERSIONla mia costruzione env è broncio oggi così non posso confermare.)

Nel caso improbabile che stai usando dietlibc , in esecuzione diet -vverrà visualizzata la versione.

(FWIW, nel corso di diversi anni con il software che utilizza autoconf ho riscontrato più problemi con le funzionalità gcce i g++requisiti non controllati che con le funzionalità glibc verificate.)


5

GNU libc (ciò che la maggior parte delle distribuzioni Linux usa in un modo o nell'altro) fa di tutto per mantenere una rigida compatibilità con le versioni precedenti. Quindi dovresti avere problemi solo se provi a eseguire un binario troppo nuovo su una vecchia versione (o una distribuzione "enterprise", normalmente congelano le versioni, in particolare quelle di base come la libreria C, eseguendo il backport delle correzioni mantenendo una rigida compatibilità binaria) . Credo che tu sia molto più soggetto a incorrere in problemi con altre librerie (il C ++ ha avuto alcune modifiche API / ABI nella memoria recente, alcune altre librerie non si preoccupano della compatibilità con le versioni precedenti).

Purtroppo, l'unico modo per scoprirlo con certezza è provare.


+1 In realtà hanno un grafico relativo alla compatibilità con le versioni precedenti e suppongo che l'unica ragione per cui non è tutto al 100% sia a causa del codice che sfrutta le estensioni GNU esoteriche. Tuttavia, non esiste un grafico del genere di cui sono a conoscenza per quanto riguarda la compatibilità futura , che come noti è più la vera preoccupazione.
Riccioli d'oro

5

(Questo è essenzialmente lo stesso della risposta dei riccioli d'oro ma con qualche spiegazione in più di ciò che sta accadendo sotto il cofano.)

La libreria condivisa principale per GNU libc, libc.so.6(su Linux; Hurd ha un SONAME diverso), ha la proprietà insolita (per le librerie condivise) che puoi invocarla come eseguibile. Se lo fai, stampa il genere di cose che di solito le utility GNU stampano quando vengono eseguite --version, in questo modo:

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

Ma ovviamente la directory in cui libc.so.6non si trova la vita $PATH, quindi devi sapere dove cercarla. Potrebbe essere in /lib, /lib64, /usr/libo qualcosa di ancora wackier (come in questo caso). Convenientemente, lddti dirò:

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

Perché funzioni, ovviamente, devi conoscere il percorso completo di un eseguibile binario collegato dinamicamente. L' sheseguibile è garantito /bin(perché molti #!script si aspettano che sia) e non può essere esso stesso uno #!script. Si potrebbe essere collegata in modo statico, ma non ho incontrato un sistema che ha fatto in tanti anni.

Non so cosa fai se corri con uClibc o musl o qualcosa di più esotico.


2
Beh, non dovete conoscere il percorso completo / bin / sh o qualsiasi altra cosa. Puoi sempre $ ldd $(which sh) | grep libc. : D
Matt Nordhoff,

5

Un altro modo per ottenerlo:

getconf GNU_LIBC_VERSION

Bello, questo dovrebbe funzionare in modo affidabile dal glibc-2.3.3.
mr.spuratic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.