Jak mogę z całą pewnością stwierdzić, jakiej biblioteki użytkownika C używa mój system? Możliwe powody, dla których potrzebne są te informacje, to:
Jest gigantyczny pakiet źródłowy, który rozważam do pobrania, który z pewnością wykona odpowiednie kontrole i wyświetli minimalną wersję biblioteki, ale wolę oszczędzić sobie potencjalnego problemu, sprawdzając najpierw, czy zadziała.
Martwię się o kompatybilność ABI z niektórymi plikami binarnymi stron trzecich, które chcę wypróbować poza systemem zarządzania pakietami systemu.
Mam pakiet źródłowy, którego dokumentacja wspomina o potrzebie minimalnej wersji biblioteki mojego systemu, ale proces kompilacji nie wykonuje żadnych kontroli.
Buduję cross-kompilator ukierunkowany na konkretny system i nie chcę ryzykować problemów z kompatybilnością .
źródło
ldd
. Nie jestem pewien, czyotool --version
można uznać, że daje te same informacje.Odpowiedzi:
Systemy GNU / Linux zwykle używają albo glibc (rodzina Fedora / Redhat, Arch) lub jego bliskiego kuzyna, eglibc (rodzina Debian / Ubuntu); ponieważ eglibc jest teraz ponownie łączony w glibc ( patrz Oddział EGLIBC 2.19 utworzony w dziale „Wiadomości” ), w niedalekiej przyszłości wszyscy będą ponownie glibc.
Najłatwiejszym sposobem sprawdzenia dokładnej wersji jest zapytanie
ldd
, która wersja jest dostarczana z biblioteką C.W Fedorze 20:
To glibc 2.18.
W systemie Raspbian (port Debian 7 dla ARMv6 Broadcom SoC):
To jest eglibc 2.13.
Jeśli z jakiegokolwiek powodu zmieszałeś i dopasowałeś niektóre części lub w inny sposób nie jesteś pewien
ldd
, możesz bezpośrednio zapytać bibliotekę C.Żaden z nich nie jest wykonywalny, ale dostarczają wskazówek, gdzie go znaleźć.
Jednak niekoniecznie jest to takie łatwe, ponieważ biblioteka C nie musi się gdzieś
whereis
znajdować, aby ją znaleźć.Niestety strona podręcznika nie podaje numeru wersji.
ldd
wciąż jest przydatny, ponieważ każdy działający, dynamicznie połączony plik wykonywalny w systemie (np. prawie wszystko w/usr/bin
) będzie łączył się z biblioteką C.libc.so.6
jest na trzeciej linii.źródło
/lib/`uname -m`*
ścieżki. Tak przenośny sposób byłoby:find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version
. Dziękuję za miłe wyjaśnienie.System nie jest w rzeczywistości ograniczony do jednej biblioteki C. Większość jednak używa przede wszystkim tylko jednego, który będzie również domyślnym kompilatorem. A ponieważ pobierasz kod źródłowy w celu kompilacji, właśnie o to się martwisz.
Zacznij od trywialnego programu:
skompiluj go za pomocą kompilatora, którego będziesz używać dla kodu źródłowego, a następnie użyj,
ldd
aby dowiedzieć się, gdzie jest biblioteka C:Masz teraz ścieżkę do biblioteki C. Możesz to sprawdzić w menedżerze pakietów, aby znaleźć pakiet (np.
dpkg -S /lib/x86_64-linux-gnu/libc.so.6
Lubrpm -q -f /lib/x86_64-linux-gnu/libc.so.6
).Przynajmniej w przypadku eglibc / glibc możesz go uruchomić:
Wreszcie, możesz sprawdzić, czy możesz uzyskać wskazówki
objdump -p /lib/x86_64-linux-gnu/libc.so.6
, przeglądając sekcję definicji wersji :Zwróć uwagę, że symbol GLIBC_2.18 ma najnowszy numer wersji spośród wymienionych symboli, a wersja biblioteki to rzeczywiście 2.18. Jest jednak eglibc (ma być binarnie kompatybilny z glibc 2.18, więc używa tych samych wersji symboli).
Możesz także spróbować
strings
dowiedzieć się czegoś na ten temat. Będziesz chciał określić dłuższą minimalną długość (-n
) lub użyj grep, aby wyszukać coś:oba działają dla tego eglibc.
UWAGA: Narzędzie pakietu Debian
dpkg-shlibdeps
używaobjdump
pod maską, wraz z przechowywanymi informacjami o symbolach w pakietach bibliotek Debiana, w celu określenia minimalnych wersji zależności wymaganych przez binarne pakiety Debiana podczas kompilacji. Zasadniczo patrzy na symbole eksportowane przez binarny pakiet Debian, a następnie znajduje minimalne wersje bibliotek, które zawierają te symbole.źródło
Oczywistą odpowiedzią, choć nie najbardziej wyczerpującą, jest sprawdzenie menedżera pakietów, np
(Niestety, glibc nie ma
.pc
pliku pkconfig , więc nie jest programem uruchamiającympkgconfig --modversion glibc
.) Zobacz także doskonałągetconf
sugestię @ Gnouc .Najprostszym przypadkiem, z gcc + glibc, i tym, którego najczęściej używam jako pierwszego, jest po prostu wykonanie
libc.so
, jak opisano w niektórych innych odpowiedziach tutaj. Nie trzeba przekazywać żadnych argumentów, domyślnie wyświetla ona swoją wersję. To działa aż do glibc-2.1 (seg-fault glibc-2.0, choć dawno temu można było sprawdzić (obecnie wycofany)glibcbug
skrypt, aby potwierdzić wersję). Ta metoda działa również z najnowszymi (> 0.9.15) wersjami musl-libc (które właśnie weszły 1.0 dzisiaj, 20 marca). Nie działa z uClibc, powoduje awarie.Jednym prostym sposobem na dokładne określenie, co
gcc
zamierzasz zrobić, jest kompilacja:(z glibc,
<stdio.h>
zawiera<features.h>
który określa odpowiednie makra glibc musisz<gnu/libc-version.h>
do deklaracji funkcji.)Łapie to bardziej złożone przypadki (wiele bibliotek libc i / lub wiele kompilatorów), zakładając oczywiście, że używasz właściwego kompilatora (i flag). (Podejrzewam, że nie rozróżnia jednak właściwego eglibc od glibc).
Jeśli masz pewność, że używasz glibc (lub eglibc)(przepraszam, to nie jest poprawne).ld
, potwierdzi również wersjęJeśli
__GNU_LIBRARY__
nie zostanie zdefiniowane, pojawią się błędy, czas na plan B.gcc -dumpmachine
może pomóc, np. dla uclibc ma-uclibc
sufiks, tak jak możegcc -dumpspecs | grep dynamic-linker
. Może to również oznaczać ABI.gcc -print-file-name=libc.so
powie ci, jakiego pliku użyje kompilator dla „-lc
”, jest to prawie na pewno skrypt łączący w instalacji gcc, który możesz odczytać jako zwykły tekst. To pokaże dokładną ścieżkę dolibc.so
. Będzie to również działać, jeśli podajesz flagi takie jak-m32
lub-m64
.W przypadku korzystania z uclibc (używanego przez OpenWRT i inne), definiuje on
__UCLIBC_MAJOR__
,__UCLIBC_MINOR__
a__UCLIBC_SUBLEVEL__
także__UCLIBC__
w<features.h>
, więc można go łatwo wykryć za pomocą niewielkiej odmiany powyższego fragmentu kodu C. W interesie kompatybilności uClibc może również definiować makra GNU / GLIBC, jak użyto powyżej, obecnie udaje, że jest glibc-2.2. Nie ma obecnie realizowaćgnu_get_libc_X()
funkcje, ale nie wdrożyćgetconf
które również mogą wprowadzać w błąd (podejrzewam, że zwraca pustą odpowiedź nagetconf GNU_LIBC_VERSION
mój build env jest dąsać dzisiaj więc nie mogę potwierdzić).W mało prawdopodobnym przypadku korzystania z dietlibc , bieganie
diet -v
wyświetli wersję.(FWIW, przez kilka lat z oprogramowaniem używającym autoconf miałem więcej problemów z niesprawdzonymi
gcc
ig++
wymaganymi wymaganiami niż z sprawdzonymi funkcjami glibc).źródło
GNU libc (to, czego używa większość dystrybucji Linuksa w tej czy innej formie) dokłada wszelkich starań, aby zachować ścisłą kompatybilność wsteczną. Dlatego powinieneś mieć kłopoty tylko wtedy, gdy spróbujesz uruchomić zbyt nowy plik binarny na starej wersji (lub dystrybucji „korporacyjnej”, zwykle zamrażają wersje, szczególnie te fundamentalne, takie jak biblioteka C, poprawki backporting przy jednoczesnym zachowaniu ścisłej zgodności binarnej) . Uważam, że jesteś znacznie bardziej narażony na problemy z innymi bibliotekami (C ++ miał kilka zmian API / ABI w ostatniej pamięci, niektóre inne biblioteki po prostu nie dbają o kompatybilność wsteczną).
Niestety jedynym sposobem, aby się przekonać, jest spróbowanie.
źródło
(Jest to w zasadzie to samo, co odpowiedź złotonośnych, ale z pewnym wyjaśnieniem tego, co dzieje się pod maską.)
Podstawowa biblioteka współdzielona dla GNU libc
libc.so.6
(w Linuksie; Hurd ma inną SONAME), ma niezwykłą właściwość (dla bibliotek współdzielonych), którą można wywołać jako plik wykonywalny. Jeśli tak, wypisuje coś, co narzędzia GNU zwykle drukują po uruchomieniu--version
, na przykład:Ale oczywiście nie ma katalogu, w którym
libc.so.6
nie ma życia$PATH
, więc musisz wiedzieć, gdzie go szukać. To może być/lib
,/lib64
,/usr/lib
, lub coś jeszcze wackier (jak w tym przypadku). Dogodnieldd
powie ci:Aby to zadziałało, oczywiście musisz znać pełną ścieżkę dynamicznie połączonego binarnego pliku wykonywalnego. Plik
sh
wykonywalny na pewno jest w/bin
(ponieważ tak wiele#!
skryptów się spodziewa) i sam nie może być#!
skryptem. To mogłaby być powiązana statycznie, ale ja nie spotkałem system, który zrobił na wiele lat.Nie wiem, co robisz, jeśli biegasz z uClibc lub muslem lub czymś bardziej egzotycznym.
źródło
$ ldd $(which sh) | grep libc
. : DInnym sposobem na uzyskanie:
źródło