Versi C library apa yang digunakan sistem saya?

43

Bagaimana saya bisa tahu dengan pasti apa yang digunakan pengguna C library yang digunakan sistem saya? Kemungkinan alasan untuk memerlukan informasi ini meliputi:

  • Ada paket sumber raksasa yang saya pertimbangkan untuk diunduh yang saya yakin akan melakukan pemeriksaan yang tepat dan mencantumkan versi pustaka mininum, tetapi saya lebih suka menghemat kerumitan dengan memeriksa dulu apakah itu akan berhasil.

  • Saya khawatir tentang kompatibilitas ABI dengan beberapa binari pihak ketiga yang ingin saya coba dan instal di luar sistem manajemen paket sistem.

  • Saya memiliki paket sumber yang dokumentasinya menyebutkan perlunya versi minimum dari pustaka sistem saya, tetapi proses pembuatannya tidak melakukan pemeriksaan apa pun.

  • Saya membangun kompilator silang yang menargetkan sistem tertentu dan tidak ingin mengambil risiko masalah kompatibilitas .

goldilocks
sumber
Mengapa tidak mencobanya dan melihatnya. Saya tidak tahu apakah versi ini memberi tahu Anda segalanya; bagaimana dengan tambalan? Atau apakah distrubusi berhati-hati dalam mengubah ABI? Bukankah masalah apakah simbol yang diekspor diselesaikan, atau semacamnya?
Faheem Mitha
Jawaban yang bagus, tetapi tidak ada yang membahas bagaimana melakukan ini pada Mac, di mana tidak ada ldd. Saya tidak yakin apakah otool --versiondapat dianggap memberikan informasi yang sama.
dubiousjim
@dubiousjim Seseorang bisa; bukan aku, karena aku bukan pengguna Mac. Di sekitar sini Anda mungkin harus bertanya secara khusus tentang hal itu - bagian dari masalah mungkin orang umumnya tidak menggunakan banyak C pada OSX? Tapi saya yakin akan ada yang biasa tahu. Anda juga dapat memposting tautan ke ini dalam obrolan dan melihat apa yang terjadi, tetapi mungkin pertanyaan baru yang lebih spesifik akan lebih baik.
goldilocks

Jawaban:

50

Sistem GNU / Linux biasanya menggunakan glibc (keluarga Fedora / Redhat, Arch) atau sepupu dekatnya, eglibc (keluarga Debian / Ubuntu); karena eglibc sekarang sedang digabungkan kembali ke glibc ( lihat EGLIBC 2.19 Cabang Dibuat di bawah "Berita" ), dalam waktu dekat mereka semua akan glibc lagi.

Cara termudah untuk memeriksa versi pastinya adalah dengan bertanya ldd, yang dikirimkan dengan pustaka C.

Pada Fedora 20:

> ldd --version
ldd (GNU libc) 2.18

Itu glibc 2.18.

Di Raspbian (port Debian 7 untuk ARMv6 Broadcom SoC):

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

Itu eglibc 2.13.

Jika karena alasan apa pun Anda telah mencampur dan mencocokkan beberapa bagian atau sebaliknya tidak yakin ldd, Anda dapat meminta pustaka C secara langsung.

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

Tidak ada yang dapat dieksekusi tetapi mereka memberikan petunjuk tentang di mana menemukannya.

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

Namun, itu tidak selalu begitu mudah, karena perpustakaan C tidak harus berada di suatu tempat whereisdapat menemukannya.

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

Sayangnya, halaman manual tidak memberikan nomor versi. lddmasih sangat berguna, karena semua yang dapat dijalankan, yang dapat dieksekusi secara dinamis dapat dieksekusi pada sistem (mis., hampir semua yang ada di dalamnya /usr/bin) akan terhubung ke pustaka 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 ada di baris ketiga.

> /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.
goldilocks
sumber
Apa yang membuat sistem GNU / Linux "normal"? Bagaimana dengan distribusi menggunakan musl ?
Elliott Frisch
1
@ElliottFrisch Ini dimaksudkan untuk diterapkan pada GNU / Linux, seperti pada, "normal GNU / Linux" (kata sifat, kata benda), karena mungkin ada (yang, saya yakin) sistem yang tidak menggunakan (e) glibc tetapi melakukan gunakan sisa tumpukan GNU (bash, binutils, dll.). Saya akan mempertimbangkan sistem GNU / Linux "tidak biasa" itu. Tetapi saya telah menghapus "normal" dan mengubahnya menjadi "Sistem GNU / Linux biasanya menggunakan ...". Catatan Saya sengaja membiarkan pertanyaan tersebut membuka spesifikasi WRT OS tertentu (tidak ada linux atau GNU atau tag glibc), jadi jika Anda ingin menambahkan jawaban mengenai sistem apa pun yang sesuai dengan U&L, silakan lakukan.
goldilocks
1
Setelah saya menemukannya seperti yang Anda tunjukkan dan saya menanyakan versi, itu juga mencetak ekstensi yang tersedia! (dalam kasus saya bertopik, crypt, libidn, utas asli dan ikat) dan disebut ABI: libc ABI: UNIK IFUNC.
Debian menggunakan /lib/`uname -m`*path. Jadi cara yang portabel akan menjadi: find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version. Terima kasih untuk penjelasannya.
pevik
@pevik: Salah, di tangan itu /lib/arm-linux-gnueabihf/libc.so.6, dan bukan /lib/armv7l/libc.so.6
Quandary
14

Sistem sebenarnya tidak terbatas pada satu pustaka C. Namun, sebagian besar hanya menggunakan satu, yang juga akan menjadi salah satu yang digunakan kompiler default. Dan karena Anda mengunduh kode sumber untuk dikompilasi, itu yang menjadi perhatian Anda.

Mulai dengan program sepele:

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

kompilasi menggunakan kompiler yang akan Anda gunakan untuk kode sumber, lalu gunakan ldduntuk mencari tahu di mana pustaka 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)

Anda sekarang memiliki jalur ke perpustakaan C. Anda bisa mencari ini di manajer paket Anda untuk menemukan paket (misalnya, dpkg -S /lib/x86_64-linux-gnu/libc.so.6atau rpm -q -f /lib/x86_64-linux-gnu/libc.so.6).

Setidaknya dalam kasus eglibc / glibc, Anda dapat menjalankannya:

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

Akhirnya, Anda bisa melihat apakah Anda bisa mendapatkan petunjuk objdump -p /lib/x86_64-linux-gnu/libc.so.6, dengan melihat di bagian definisi versi :

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 

Perhatikan bagaimana simbol GLIBC_2.18 memiliki nomor versi terbaru di antara simbol yang terdaftar, dan versi pustaka memang 2,18. Ini eglibc, meskipun (ini bertujuan agar kompatibel dengan biner dengan glibc 2.18, jadi ia menggunakan versi simbol yang sama).

Anda juga dapat mencoba menggunakannya stringsuntuk menemukan sesuatu tentang itu. Anda ingin menentukan panjang minimal yang lebih panjang ( -n), atau menggunakan grep untuk mencari sesuatu:

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

keduanya bekerja untuk eglibc ini.

CATATAN: Utilitas paket Debian dpkg-shlibdepsmenggunakan di objdumpbawah tenda, bersama dengan informasi simbol yang tersimpan dalam paket perpustakaan Debian untuk menentukan versi minimum dependensi yang diperlukan oleh paket biner Debian pada waktu pembuatan. Pada dasarnya, ini terlihat pada simbol yang diekspor oleh paket biner Debian, dan kemudian menemukan versi minimum dari pustaka yang berisi simbol-simbol tersebut.

derobert
sumber
9

Jawaban yang jelas, meskipun bukan yang paling komprehensif, adalah memeriksa manajer paket Anda, mis

rpm -qi glibc
dpkg -l libc6

(Sedihnya, glibc tidak memiliki .pcfile pkconfig , begitu pkgconfig --modversion glibcjuga non-runner.) Lihat juga getconfsaran luar biasa @ Gnouc .

Kasus paling sederhana, dengan gcc + glibc, dan yang paling sering saya gunakan pertama adalah dengan mengeksekusi libc.so, seperti yang dijelaskan dalam beberapa jawaban lain di sini. Tidak perlu melewati argumen apa pun, itu mengeluarkan versinya secara default. Ini berfungsi sejauh glibc-2.1 (glibc-2.0 seg-faults, meskipun saat itu Anda dapat memeriksa glibcbugskrip (sekarang sudah pensiun) untuk mengonfirmasi versi). Metode ini juga berfungsi dengan versi musl -libc ( > 0.9.15) terbaru (yang baru berjalan 1.0 hari ini, 20 Maret). Itu tidak bekerja dengan uClibc, itu segfaults.

Salah satu cara sederhana untuk mengetahui dengan pasti apa gccyang akan Anda lakukan adalah mengkompilasi:

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

(dengan glibc, <stdio.h>termasuk <features.h>yang mendefinisikan makro GLIBC yang relevan, Anda perlu <gnu/libc-version.h>deklarasi fungsi.)

Ini menangkap kasus yang lebih rumit (multiple libc's, dan / atau multiple compiler), dengan asumsi Anda menggunakan kompiler yang tepat (dan flag) tentu saja. (Saya menduga itu tidak akan membedakan antara eglibc dan glibc yang tepat.)

Jika Anda yakin Anda menggunakan glibc (atau eglibc) maka ldjuga akan mengkonfirmasi versi (maaf, ini tidak benar).

Jika __GNU_LIBRARY__tidak didefinisikan Anda akan mendapatkan kesalahan, maka sudah saatnya untuk rencana B.

gcc -dumpmachinedapat membantu, misalnya untuk uclibc -uclibc, suffix memiliki akhiran gcc -dumpspecs | grep dynamic-linker. Ini juga dapat menyiratkan ABI.

gcc -print-file-name=libc.soakan memberi tahu Anda file apa yang akan digunakan kompiler untuk " -lc", ini hampir pasti merupakan skrip-tautan di dalam instalasi gcc Anda, yang dapat Anda baca sebagai teks biasa. Itu akan menunjukkan jalur yang tepat ke libc.so. Ini juga akan berfungsi jika Anda memberikan tanda suka -m32atau -m64.

Jika Anda menggunakan uclibc (seperti yang digunakan oleh OpenWRT dan lainnya), ia mendefinisikan __UCLIBC_MAJOR__, __UCLIBC_MINOR__dan __UCLIBC_SUBLEVEL__juga __UCLIBC__dalam <features.h>, sehingga mudah dideteksi menggunakan variasi kecil pada cuplikan kode C di atas. Demi kompatibilitas, uClibc juga dapat mendefinisikan makro GNU / GLIBC seperti yang digunakan di atas, saat ini berpura-pura menjadi glibc-2.2. Ini saat ini tidak melaksanakan gnu_get_libc_X()fungsi, tetapi tidak melaksanakan getconfyang juga dapat menyesatkan (saya menduga itu mengembalikan jawaban kosong untuk getconf GNU_LIBC_VERSION, saya membangun env yang merajuk hari ini jadi saya tidak bisa mengkonfirmasi.)

Jika Anda menggunakan dietlibc , menjalankan diet -vakan menampilkan versi.

(FWIW, selama beberapa tahun dengan perangkat lunak menggunakan autoconf, saya punya lebih banyak masalah dengan uncheck-for gccdan g++persyaratan daripada dengan diperiksa-untuk fitur glibc.)

mr.spuratic
sumber
5

GNU libc (apa yang digunakan sebagian besar distribusi Linux dalam satu bentuk atau yang lain) berusaha keras untuk menjaga kompatibilitas mundur. Jadi, Anda harus mengalami masalah hanya jika Anda mencoba menjalankan biner yang terlalu baru pada versi lama (atau distribusi "perusahaan", mereka biasanya membekukan versi, terutama yang dasar seperti perpustakaan C, perbaikan backporting sambil menjaga kompatibilitas biner yang merusak) . Saya percaya Anda jauh lebih mungkin mengalami masalah dengan perpustakaan lain (C ++ memiliki beberapa perubahan API / ABI dalam memori baru-baru ini, beberapa perpustakaan lain hanya tidak peduli untuk kompatibilitas ke belakang).

Sedihnya, satu-satunya cara untuk mengetahui dengan pasti adalah dengan mencoba.

vonbrand
sumber
+1 Sebenarnya mereka memiliki bagan tentang kompatibilitas ke belakang dan saya akan mengasumsikan satu-satunya alasan tidak semuanya 100% adalah karena kode yang mengeksploitasi ekstensi GNU esoterik. Namun, tidak ada bagan seperti itu yang saya ketahui tentang kompatibilitas ke depan , yang seperti yang Anda perhatikan lebih merupakan masalah nyata.
goldilocks
5

(Ini pada dasarnya sama dengan jawaban goldilocks tetapi dengan penjelasan lebih lanjut tentang apa yang terjadi di bawah tenda.)

Pustaka bersama inti untuk GNU libc, libc.so.6(di Linux; Hurd memiliki SONAME berbeda), memiliki properti yang tidak biasa (untuk pustaka bersama) yang dapat Anda gunakan sebagai executable. Jika ya, itu akan mencetak hal-hal yang biasanya dicetak oleh utilitas GNU ketika dijalankan --version, seperti ini:

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

Tapi tentu saja direktori tempat libc.so.6tinggal tidak ada $PATH, jadi Anda harus tahu di mana mencarinya. Mungkin di /lib, /lib64, /usr/lib, atau sesuatu yang bahkan wackier (seperti dalam kasus ini). Dengan mudah, lddakan memberi tahu Anda:

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

Agar itu berfungsi, tentu saja, Anda harus mengetahui pathname lengkap dari eksekusi biner yang terhubung secara dinamis. Dapat shdieksekusi dijamin berada di /bin(karena begitu banyak #!skrip mengharapkannya), dan tidak dapat dengan sendirinya menjadi #!skrip. Ini bisa menjadi statis terkait, tapi saya belum menemukan sebuah sistem yang melakukan itu bertahun-tahun.

Saya tidak tahu apa yang Anda lakukan jika Anda menggunakan uClibc atau musl atau sesuatu yang lebih eksotis.

zwol
sumber
2
Nah, Anda tidak perlu tahu path lengkap ke / bin / sh atau apa pun. Kamu selalu bisa $ ldd $(which sh) | grep libc. : D
Matt Nordhoff
5

Cara lain untuk mendapatkannya:

getconf GNU_LIBC_VERSION
cuonglm
sumber
Bagusnya, ini harus bekerja dengan andal sejak glibc-2.3.3.
mr.spuratic