Co oznacza błąd „brak dostępnych informacji o wersji” z dynamicznego linkera linuxa?

89

W naszym produkcie dostarczamy pliki binarne Linuksa, które dynamicznie łączą się z bibliotekami systemowymi, takimi jak „libpam”. W niektórych systemach klientów otrzymujemy następujący błąd na stderr po uruchomieniu programu:

./authpam: /lib/libpam.so.0: no version information available (required by authpam)

Aplikacja działa dobrze i wykonuje kod z biblioteki dynamicznej. Więc to nie jest błąd krytyczny, to tak naprawdę tylko ostrzeżenie.

Wydaje mi się, że to błąd pochodzi z dynamicznego konsolidatora, gdy w bibliotece zainstalowanej w systemie brakuje czegoś, czego oczekuje nasz plik wykonywalny. Nie wiem zbyt wiele o wewnętrznych elementach procesu dynamicznego linkowania ... a wyszukiwanie tego tematu w Google niewiele pomaga. :(

Czy ktoś wie, co powoduje ten błąd? ... jak mogę zdiagnozować przyczynę? ... i jak moglibyśmy zmienić nasze pliki wykonywalne, aby uniknąć tego problemu?

Aktualizacja: klient dokonał aktualizacji do najnowszej wersji „testowania” Debiana i wystąpił ten sam błąd. Więc nie jest to przestarzała biblioteka libpam. Chyba chciałbym zrozumieć, na co skarży się linker? Jak mogę zbadać przyczynę itp.?


źródło

Odpowiedzi:

64

„Brak dostępnych informacji o wersji” oznacza, że ​​numer wersji biblioteki jest niższy w udostępnionym obiekcie. Na przykład, jeśli numer major.minor.patch to 7.15.5 na komputerze, na którym budujesz plik binarny, a numer major.minor.patch to 7.12.1 na komputerze instalacyjnym, ld wydrukuje ostrzeżenie.

Możesz to naprawić, kompilując z biblioteką (nagłówki i obiekty udostępnione), która jest zgodna z wersją obiektu współużytkowanego dostarczoną z docelowym systemem operacyjnym. Na przykład, jeśli zamierzasz zainstalować w RedHat 3.4.6-9, nie chcesz kompilować na Debianie 4.1.1-21. Jest to jeden z powodów, dla których większość dystrybucji obsługuje określone numery dystrybucji Linuksa.

W przeciwnym razie możesz łączyć statycznie. Jednak nie chcesz tego robić za pomocą czegoś takiego jak PAM, więc chcesz faktycznie zainstalować środowisko programistyczne, które pasuje do środowiska produkcyjnego twojego klienta (lub przynajmniej zainstalować i połączyć z odpowiednimi wersjami biblioteki).

Porada dotycząca zmiany nazw plików .so (uzupełnianie ich numerami wersji) pochodzi z czasów, gdy biblioteki obiektów współdzielonych nie używały symboli wersjonowanych. Więc nie spodziewaj się, że gra ze schematem nazewnictwa .so.nnn pomoże (bardzo - może pomóc, jeśli system został zniszczony).

Ostatnią opcją będzie kompilacja z biblioteką z innym pomniejszym numerem wersji, przy użyciu niestandardowego skryptu łączącego: http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts. html

Aby to zrobić, musisz napisać niestandardowy skrypt i będziesz potrzebować niestandardowego instalatora, który uruchamia ld na obiektach udostępnionych klienta, używając niestandardowego skryptu. Wymaga to, aby twój klient miał gcc lub ld w swoim systemie produkcyjnym.

Chris
źródło
21

Ta wiadomość z dynamicznego linkera glibc właściwie oznacza, że ​​wspomniana biblioteka ( /lib/libpam.so.0w twoim przypadku) nie ma VERDEFsekcji ELF, podczas gdy plik binarny ( authpamw twoim przypadku) ma pewne definicje wersji w VERNEEDsekcji dla tej biblioteki (prawdopodobnie libpam.so.0). Można łatwo zobaczyć ją readelf, po prostu patrzeć .gnu.version_di .gnu.version_rsekcjach (lub jej brak).

Więc nie jest to niezgodność wersji symbolu, ponieważ jeśli plik binarny chciałby pobrać jakąś konkretną wersję przez, VERNEEDa biblioteka nie dostarczyła jej w swojej rzeczywistej VERDEF, byłby to twardy błąd konsolidatora, a plik binarny w ogóle nie działałby (w ten sposób w porównaniu z tym lub innym ). Chodzi o to, że plik binarny chce niektórych wersji, ale biblioteka nie dostarcza żadnych informacji o jego wersjach.

Co to oznacza w praktyce? Zwykle dokładnie to, co widać w tym przykładzie - nic, po prostu działa ignorowanie wersjonowania. Czy coś mogło się zepsuć? Oczywiście tak, więc pozostałe odpowiedzi są poprawne w tym, że należy używać tych samych bibliotek w czasie wykonywania, z którymi był połączony plik binarny w czasie kompilacji.

Więcej informacji można znaleźć w Ulrich Dreppers „ELF Symbol Versioning” .

Roman Khimov
źródło
5
Zalecam uruchomienie „readelf -V <exePath>”, aby zobaczyć sekcję dotyczącą wersjonowania. uwaga kapitał V
Rayee Roded
Wydedukowałem, że był to powód ostrzeżenia dotyczącego (nowszych! Wersji systemu) bibliotek, które sam buduję i instaluję w równoległym prefiksie. Zawsze myślałem, że dzieje się tak, ponieważ używam łańcucha narzędzi LLVM, ale właśnie zauważyłem, że budowanie z systemem gcc nie umieszcza tych tagów wersji automatycznie w bibliotece. Czy muszę dodać opcję przez CFLAGS i / lub LDFLAGS?
RJVB
5

Fwiw, miałem ten problem podczas uruchamiania check_nrpe w systemie, który miał zainstalowany system monitorowania zenoss. Aby dodać do zamieszania, działał dobrze jako użytkownik root, ale nie jako użytkownik zenoss.

Dowiedziałem się, że użytkownik zenoss miał LD_LIBRARY_PATH, która spowodowała, że ​​używał bibliotek zenoss, które generują te ostrzeżenia. To znaczy:

root@monitoring:$ echo $LD_LIBRARY_PATH

su - zenoss
zenoss@monitoring:/root$ echo $LD_LIBRARY_PATH
/usr/local/zenoss/python/lib:/usr/local/zenoss/mysql/lib:/usr/local/zenoss/zenoss/lib:/usr/local/zenoss/common/lib::
zenoss@monitoring:/root$ /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
/usr/lib/nagios/plugins/check_nrpe: /usr/local/zenoss/common/lib/libcrypto.so.0.9.8: no version information available (required by /usr/lib/libssl.so.0.9.8)
(...)
zenoss@monitoring:/root$ LD_LIBRARY_PATH= /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
(...)

W każdym razie, co próbuję powiedzieć: sprawdź również zmienne, takie jak LD_LIBRARY_PATH, LD_PRELOAD itp.

Dieter_be
źródło
3

Jak kompilujesz swoją aplikację? Jakie flagi kompilatora?

Z mojego doświadczenia wynika, że ​​gdy celujesz w rozległy obszar systemów Linux, twórz pakiety na najstarszej wersji, którą chcesz obsługiwać, a ponieważ więcej systemów jest kompatybilnych wstecz, Twoja aplikacja będzie nadal działać. Właściwie to jest cały powód wersjonowania bibliotek - zapewnienie kompatybilności wstecznej.

Ted Percival
źródło
1

Widziałeś to już? Przyczyną wydaje się być bardzo stara biblioteka libpam po jednej ze stron, prawdopodobnie po stronie tego klienta.

Lub może brakować linków do wersji: http://www.linux.org/docs/ldp/howto/Program-Library-HOWTO/shared-libraries.html

Vinko Vrsalovic
źródło
Znalazłem to, ale tak naprawdę nie pomogło to w zrozumieniu przyczyny. Nie wydaje mi się, żeby to była stara biblioteka PAM, ponieważ zaktualizowali ją do najnowszych testów Debiana.
Więc może kompilujesz na starej maszynie? :) Czy próbowałeś skompilować go na komputerze klienta? nondot.org/sabre/Mirrored/libtool-2.1a/libtool_toc.html#TOC36
Vinko Vrsalovic