Próbuję dowiedzieć się więcej o wersjonowaniu bibliotek w systemie Linux i o tym, jak to wszystko uruchomić. Oto kontekst:
- Mam dwie wersje biblioteki dynamicznej, która udostępnia ten sam zestaw interfejsów, powiedzmy libsome1.so
i libsome2.so
.
- Aplikacja jest połączona z libsome1.so
.
- Ta aplikacja używa libdl.so
do dynamicznego ładowania innego modułu, powiedzmy libmagic.so
.
- Teraz libmagic.so
jest powiązany z libsome2.so
. Oczywiście, bez użycia skryptów linkera do ukrywania symboli libmagic.so
, w czasie wykonywania wszystkie wywołania interfejsów libsome2.so
są przetwarzane libsome1.so
. Można to potwierdzić, porównując wartość zwracaną przez libVersion()
z wartością makra LIB_VERSION
.
- Więc próbuję następnie skompilować i połączyć libmagic.so
ze skryptem linkera, który ukrywa wszystkie symbole oprócz 3, które są w nim zdefiniowane libmagic.so
i są przez niego eksportowane. To działa ... albo przynajmniej libVersion()
i LIB_VERSION
wartości dopasowania (i zgłasza wersji 2 nie 1).
- Jednak gdy niektóre struktury danych są serializowane na dysk, zauważyłem pewne uszkodzenie. Jeśli w katalogu aplikacji usunę libsome1.so
i utworzę miękki link w jego miejscu, aby wskazać libsome2.so
, wszystko działa zgodnie z oczekiwaniami i takie samo uszkodzenie nie występuje.
Nie mogę przestać myśleć, że może to być spowodowane konfliktem w rozdzielczości symboli łącznika w czasie wykonywania. Próbowałem wielu rzeczy, takich jak próba połączenia libsome2.so
, aby wszystkie symbole były wyrównane symbol@@VER_2
( do czego wciąż jestem zdezorientowany, ponieważ polecenie nm -CD libsome2.so
nadal wyświetla symbole jako symbol
i nie symbol@@VER_2
) ... Wydaje się, że nic nie działa !!! Wsparcie!!!!!!
źródło
RTLD_LOCAL
iRTLD_DEEPBIND
dlopen w swojej aplikacji. Nie mam teraz czasu na testowanie tego, ale powinno działać w oparciu o stronę podręcznika.Odpowiedzi:
To nie odpowiada dokładnie na twoje pytanie, ale ...
Po pierwsze, ELF jest specyfikacją używaną przez Linux dla plików wykonywalnych (programów), bibliotek współdzielonych, a także plików obiektowych, które są plikami pośrednimi znalezionymi podczas kompilacji oprogramowania. Pliki obiektów kończą się na .o, biblioteki współdzielone kończą się na .so, po którym następuje zero lub więcej cyfr oddzielonych kropkami, a pliki wykonywalne nie mają normalnie żadnych rozszerzeń.
Zazwyczaj istnieją trzy formularze określające bibliotekę współdzieloną, pierwsza forma kończy się na .so. Na przykład biblioteka o nazwie readline jest przechowywana w pliku o nazwie libreadline.so i normalnie znajduje się w katalogu / lib, / usr / lib lub / usr / local / lib. Ten plik znajduje się podczas kompilacji oprogramowania z opcją -lreadline. -l każe kompilatorowi połączyć się z następującą biblioteką. Ponieważ biblioteki zmieniają się od czasu do czasu, mogą stać się przestarzałe, dlatego biblioteki zawierają coś o nazwie SONAME. SONAME dla readline może wyglądać jak libreadline.so.2 dla drugiej wersji głównej wersji libreadline. Może być także wiele mniejszych wersji readline, które są kompatybilne i nie wymagają ponownej kompilacji oprogramowania. Niewielka wersja readline może nazywać się libreadline.so.2.14. Zwykle libreadline. więc jest to tylko symboliczny link do najnowszej głównej wersji readline, libreadline.so.2 w tym przypadku. libreadline.so.2 jest także dowiązaniem symbolicznym do libreadline.so.2.14, który jest faktycznie używanym plikiem.
SONAME biblioteki jest osadzony w samym pliku biblioteki. Gdzieś w pliku libreadline.so.2.14 znajduje się ciąg libreadline.so.2. Kiedy program zostanie skompilowany i połączony z readline, wyszuka plik libreadline.so i przeczyta osadzoną w nim SONAME. Później, kiedy program zostanie faktycznie uruchomiony, załaduje libreadline.so.2, a nie tylko libreadline.so, ponieważ była to nazwa SONAME, którą odczytano podczas pierwszego połączenia. Pozwala to systemowi na zainstalowanie wielu niekompatybilnych wersji readline, a każdy program załaduje odpowiednią wersję główną, z którą był połączony. Ponadto, uaktualniając readline, powiedzmy, do 2.17, mogę po prostu zainstalować libreadline.so.2.17 wraz z istniejącą biblioteką, a po przeniesieniu dowiązania symbolicznego libreadline.so.2 z libreadline.so.2.13 do libreadline.so.2.17,
źródło