Sistemim hangi C kütüphanesi sürümünü kullanıyor?


43

Sistemimin hangi userland C kütüphanesini kullandığından nasıl emin olabilirim? Bu bilgiye ihtiyaç duymanın olası sebepleri arasında şunlar bulunmaktadır:

  • Uygun kontroller yapıp, bir mininum kütüphanesi sürümü listeleyeceğinden emin olduğum, indirmeyi düşündüğüm dev bir kaynak paketi var, ancak çalışıp çalışmadığını kontrol ederek kendimi potansiyel bir güçlükten kurtarmayı tercih ederim.

  • Sistemin paket yönetim sisteminin dışında denemek ve kurmak istediğim bazı üçüncü taraf ikili dosyalarla ABI uyumluluğu konusunda endişeliyim .

  • Belgelerinin sistem kütüphanesinin asgari sürümüne ihtiyaç duyduğundan bahseden bir kaynak paketi var, ancak derleme işlemi herhangi bir kontrol yapmıyor.

  • Belirli bir sistemi hedefleyen bir çapraz derleyici yapıyorum ve uyumluluk sorunlarını ileriye götürmek istemiyorum .


Neden denemiyor ve göremiyorsun? Sürüm size herşeyi anlatır mı bilmiyorum; yamalar? Yoksa dağılımlar ABI'yi değiştirmek konusunda dikkatli midir? Dışa aktarılan sembollerin çözülüp çözülmediği veya bunun gibi bir şey değil mi?
Faheem Mitha

Güzel cevaplar, ancak hiç kimse bunun olmadığı bir Mac'de nasıl yapılacağını ele almıyor ldd. otool --versionAynı bilgiyi verip vermeyeceğinden emin değilim .
dubiousjim

@dubiousjim Birisi olabilir; Sadece ben değilim çünkü Mac kullanıcısı değilim. Buralarda özellikle bunun hakkında soru sormanız gerekebilir - sorunun bir kısmı belki de insanlar genellikle OSX'te düz C kullanmıyor mu? Ama eminim bilen bir düzenli olacak. Ayrıca, sohbette buna bir bağlantı gönderebilir ve ne olacağını görebilirsiniz, ancak muhtemelen yeni, daha belirgin bir soru daha iyi olurdu.
goldilocks

Yanıtlar:


50

GNU / Linux sistemleri genellikle ya glibc (Fedora / Redhat ailesi, Arch) ya da yakın kuzeni, eglibc (Debian / Ubuntu ailesi); eglibc şimdi tekrar glibc ile birleştirildiğinden ( bakınız "Haberler" altında oluşturulan EGLIBC 2.19 Şubesi ), yakın gelecekte hepsi tekrar glibc olacak.

Kesin sürümü kontrol etmenin en kolay yolu ldd, hangisinin C kütüphanesiyle birlikte geldiğini sormak .

Fedora 20’de:

> ldd --version
ldd (GNU libc) 2.18

Bu glibc 2.18.

Raspbian'da (ARMv6 Broadcom SoC için Debian 7 bağlantı noktası):

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

Bu, örneğin liblib 2.13.

Herhangi bir nedenden ötürü bazı parçaları karıştırıp eşleştirdiyseniz veya başka bir şey hakkında emin ldddeğilseniz, doğrudan C kütüphanesini sorgulayabilirsiniz.

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

Bunların hiçbiri çalıştırılabilir değil, ancak bir tanesinin nerede bulunacağına dair bir ipucu sağlıyor.

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

Ancak, mutlaka bu kadar kolay değil, çünkü C kütüphanesinde bir yerde kalması gerekmiyor whereis.

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

Ne yazık ki, man sayfası sürüm numarası sağlamıyor. lddhala kullanışlı, çünkü sistemde çalışan, dinamik olarak bağlanan herhangi bir çalıştırılabilir (örneğin, hemen hemen her şey /usr/bin) C kütüphanesine bağlanacaktır.

> 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 üçüncü sırada.

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

GNU / Linux sistemini "normal" yapan şey nedir? Musl kullanan dağılımlar ne olacak ?
Elliott Frisch

1
@ElliottFrisch O olabilir çünkü (Eminim vardır), (sıfat, isim) "normal GNU / Linux", olduğu gibi GNU / Linux sistemleri uygulamak için tasarlanmıştı yok kullanmak (e) glibc ama do GNU yığınının kalanını kullanın (bash, binutils, vs.). Bu "sıradışı" GNU / Linux sistemlerini düşünürdüm. Ama ben "normal" i kaldırdım ve "GNU / Linux sistemleri genellikle ..." kullanıyor. Not WRT işletim sistemi özelliklerini (linux veya GNU veya glibc etiketi yok) açık bir soru bıraktım , bu nedenle U&L'ye uygun herhangi bir sistemle ilgili bir cevap eklemek istiyorsanız, lütfen yapın.
goldilocks

1
Gösterdiğin gibi bulduktan ve sürümü sorguladığımda, mevcut uzantıları da yazdırdım! (benim durumumda taslaklar, kripti, libidn, doğal iplikler ve ciltleme) ve ABI'ye atıfta bulunuldu: libc ABI'ler: UNIQUE IFUNC.

Debian /lib/`uname -m`*yolu kullanır . Yani taşınabilir şekilde olacaktır: find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version. Güzel açıklama için teşekkürler.
pevik

@pevik: Yanlış, kolda /lib/arm-linux-gnueabihf/libc.so.6, ve /lib/armv7l/libc.so.6 değil
Quandary

14

Bir sistem aslında bir C kütüphanesi ile sınırlı değildir. Yine de çoğu, esas olarak yalnızca birini kullanır; bu, varsayılan derleyicinin kullandığı da olacaktır. Ve derlemek için kaynak kodu indirdiğiniz için, endişelendiğiniz kişi budur.

Önemsiz bir programla başlayın:

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

Kaynak kod için kullanacağınız derleyiciyi kullanarak derleyin, sonra lddC kütüphanesinin nerede olduğunu bulmak için kullanın :

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

Artık C kütüphanesine giden yolunuz var. Bu paketi bulmak için paket yöneticinize bakabilirsiniz (örn . dpkg -S /lib/x86_64-linux-gnu/libc.so.6Veya rpm -q -f /lib/x86_64-linux-gnu/libc.so.6).

En azından eglibc / glibc olması durumunda çalıştırabilirsiniz:

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

Son olarak, sürüm tanımları bölümüne objdump -p /lib/x86_64-linux-gnu/libc.so.6bakarak ipuçlarını alıp alamayacağınızı görebilirsiniz :

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 sembolünün, listelenen semboller arasında en son sürüm numarasına sahip olduğunu ve kütüphane sürümünün gerçekten 2,18 olduğunu unutmayın. Yine de eglibc, (glibc 2.18 ile ikili uyumlu olmayı hedefliyor, bu yüzden aynı sembol versiyonlarını kullanıyor).

stringsBununla ilgili bir şeyler bulmak için de kullanmayı deneyebilirsiniz . Daha uzun bir minimum uzunluk ( -n) belirtmek veya bir şey aramak için grep kullanmak istersiniz :

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

her ikisi de bu eglibc için çalışıyor.

NOT: Debian paketi yardımcı programı , derleme sırasında ikili Debian paketlerinin gerektirdiği minimum bağımlılık sürümlerini belirlemek için Debian kitaplık paketlerinde depolanan sembol bilgileriyle birlikte başlık altında dpkg-shlibdepskullanır objdump. Temel olarak, ikili Debian paketi tarafından verilen sembollere bakar ve bu sembolleri içeren kütüphanelerin minimum versiyonlarını bulur.


9

Açık cevap, en kapsamlı olmasa da, paket yöneticinizi kontrol etmek, örneğin;

rpm -qi glibc
dpkg -l libc6

(Ne yazık ki, glibc bir pkconfig .pcdosyasına sahip değil , bu yüzden pkgconfig --modversion glibckoşucu değil.) Ayrıca bkz. @ Gnouc'un mükemmel getconfönerisi.

En basit durum, gcc + glibc ve çoğunlukla ilk kullandığım libc.so, buradaki diğer cevapların bazılarında belirtildiği gibi sadece yürütmektir . Herhangi bir argüman iletmeye gerek yoktur, varsayılan olarak sürümünü çıkarır. Bu, glibc-2.1'e (glibc-2.0 seg-faults) kadar uzanır, ancak o zamana glibcbugdek (şimdi emekli olan) betiği onaylamak için betiği kontrol edebilirsiniz ). Bu yöntem aynı zamanda musl-libc'nin (bugün sadece 20 Mart'ta 1.0 olan ) son sürümleri (> 0.9.15) ile çalışır . UClibc ile çalışmıyor, segfaults.

Tam olarak ne yapacağınızı söylemenin basit bir yolu gccderlemek:

#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 ile ilgili GLIBC makrolarını tanımlayanları <stdio.h>içerir , fonksiyon bildirimleri için <features.h>ihtiyacınız vardır <gnu/libc-version.h>.)

Bu, tabii ki doğru derleyiciyi (ve bayrakları) kullandığınızı varsayarsak, daha karmaşık vakalar (çoklu libc'ler ve / veya çoklu derleyiciler) yakalar. (Örnegin eglibc ve glibc arasindakileri ayrilamayacaktir diye dusunuyorum.)

Eğer glibc kullandığınızdan eminseniz (veya eglibc) o ldzaman sürümü de teyit edersiniz (üzgünüm, bu doğru değil).

__GNU_LIBRARY__Tanımlı değilse , hata alırsınız, o zaman B planı zamanıdır.

gcc -dumpmachineyardımcı olabilir, örneğin uclibc için, bunun gibi bir -uclibcsonek vardır gcc -dumpspecs | grep dynamic-linker. Bu aynı zamanda ABI anlamına da gelebilir.

gcc -print-file-name=libc.soderleyicinin " -lc" için hangi dosyayı kullanacağını söyleyecektir , bu, kesinlikle kesinlikle gcc kurulumunuzda düz metin olarak okuyabileceğiniz bir linker-betiğidir. Bu tam yolu gösterecektir libc.so. Eğer böyle bayraklarını geçiriyorsanız, bu da çalışacaktır -m32ya -m64.

Durumunda kullandığınız uClibc (OpenWRT tarafından ve daha kullanıldığı gibi), tanımladığı, __UCLIBC_MAJOR__, __UCLIBC_MINOR__ve __UCLIBC_SUBLEVEL__yanı sıra __UCLIBC__içinde <features.h>kolayca C üzerinde kod parçacığı üzerinde küçük bir varyasyonu kullanılarak algılandığı oluyor böylece. Uyumluluk amacıyla, uClibc ayrıca yukarıda kullanıldığı gibi GNU / GLIBC makrolarını da tanımlayabilir, şu anda glibc-2.2 gibi görünüyor. Şu anda uygulamıyor gnu_get_libc_X()işlevleri, ancak vermez uygulamak getconf(Ben için boş bir cevap verir şüpheli de yanıltabilir hangi getconf GNU_LIBC_VERSIONyüzden onayla olamaz benim yapı env bugün somurtarak edilir.)

Olası bir olayda dietlibc kullanıyorsanız diet -v, sürümü çalıştırıyor görünecektir.

(FWIW, autoconf kullanan yazılımla birkaç yıldan fazla, kontrol edilmeyen gccve g++gereklilikleri kontrol edilen glibc özelliklerinden daha fazla sorun yaşadım .)


5

GNU libc (çoğu Linux dağıtımının bir biçimde ya da diğerinde kullandığı şey), sıkı bir şekilde geriye dönük uyumluluğu korumak için çok uzun sürmektedir. Bu nedenle, yalnızca eski bir sürümde (veya bir "kurumsal" dağıtımda çok yeni bir ikili çalıştırmaya çalışırsanız), normalde sürümleri dondururlar, özellikle C kütüphanesi gibi temel kurulumları düzeltirler, bu nedenle sabit ikili uyumluluğu korurlar. . Ben çok (C ++ birkaç API / ABI son bellek, diğer bazı kütüphaneler sadece değiştirir vardı diğer kütüphanelerle sorunlarla konusunda daha güvenilir olduğuna inanıyoruz yok geriye dönük uyumluluk için bakım).

Ne yazık ki, kesin olarak öğrenmenin tek yolu denemektir.


+1 Aslında geriye dönük uyumluluk ile ilgili bir çizelgeleri var ve bunun% 100 olmamalarının tek nedeni ezoterik GNU uzantılarını kullanan kodlardan kaynaklandığını varsayıyordum. Ancak, ileriye dönük uyumluluk ile ilgili farkında olduğum bir grafik yok ; not ettiğiniz gibi asıl mesele bu.
goldilocks

5

(Bu, temelde goldilocks'un cevabı ile aynıdır ancak kaputun altında neler olup bittiğinin bir açıklaması ile).

GNU libc için çekirdek paylaşımlı kütüphane libc.so.6(Linux'ta; Hurd'da farklı bir SONAME vardır), çalıştırılabilir olarak çağırabileceğiniz olağandışı özelliklere (paylaşılan kütüphaneler için) sahiptir. Bunu yaparsanız, GNU yardımcı programlarının genellikle çalıştırırken yazdırdıkları türden bir şey yazar --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/>.

Ama elbette, libc.so.6hayatların içinde olmadığı bir dizin $PATH, bu yüzden onu nerede arayacağınızı bilmek zorundasınız. Bu kalmış olabilir /lib, /lib64, /usr/lib, veya (bu durumda olduğu gibi) bile wackier şey. Uygun bir şekilde lddsize söyleyeceğim:

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

Bunun için, elbette, dinamik olarak bağlanmış bir ikili çalıştırılabilir dosyanın tam yolunu bilmeniz gerekir. shYürütülebilir içinde olması sağlanır /bin(pek çok nedeni #!komut olmasını bekliyoruz) ve kendisi olamaz #!komut dosyası. Bu olabilir durağan ilintilidir, ancak yıllardır yaptım bir sistem karşılaşmadım.

Eğer uClibc veya musl ile ya da daha egzotik bir şeyle çalışıyorsan ne yaparsın bilmiyorum.


2
Eh, yok olması için / bin / sh ya da her neyse tam yolunu bilmek. Her zaman yapabilirsin $ ldd $(which sh) | grep libc. : D
Matt Nordhoff

5

Bunu elde etmenin başka bir yolu:

getconf GNU_LIBC_VERSION

İyiydi, bu olmalıdır glibc'nin-2.3.3 beri güvenilir çalışır.
mr.spuratic
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.