Znajdź, gdzie jest symbol współdzielonej biblioteki zdefiniowany w systemie na żywo / wyświetl listę wszystkich symboli wyeksportowanych do systemu


21

Zasadniczo są to dwa pytania w jedno - ponieważ jeśli mogę wymienić wszystkie symbole wyeksportowane w systemie wraz z ich ścieżką do biblioteki współdzielonej, to mógłbym po prostu uzyskać grepten wynik.

W przypadku symboli jądra wydaje mi się, że jest to nieco łatwiejsze - ponieważ zawsze możemy cat /proc/kallsymsuzyskać listę wszystkich symboli modułów załadowanych do pamięci; następnie sudo cat /proc/modulespoda listę załadowanych modułów wraz z ich adresami, ale nie ścieżek, z których moduły zostały załadowane (jeśli są zbudowane jako osobne, niepasujące obiekty .ko)

Na przykład próbuję śledzić program kstprzy użyciu ltrace:

$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
...

... i chciałbym wiedzieć, gdzie to się _ZNK13QGraphicsItem10parentItemEvznajduje.

Co więc zrobić z symbolami biblioteki współdzielonej? Czytanie za pomocą [gcc-help] Re: znalezienie biblioteki, w której zdefiniowano symbol. ; Próbowałem czegoś takiego:

$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...

... ale to daje mi dodatkowe problemy: tak naprawdę nie znam wszystkich ścieżek skanowanych w poszukiwaniu bibliotek współdzielonych w moim systemie, więc kiedy po raz pierwszy spróbowałem find /lib ..., nic nie znalazło; Zgadywanie katalogów jest dla mnie irytujące, podobnie jak alternatywa: skanowanie całego głównego systemu plików za pomocą find... I wydaje mi się, że trafiłem na * .so, które nie mogą zostać otwarte nm(może dlatego, że są dowiązaniami symbolicznymi?), Które wypisuje sporo komunikatów o błędach (których mi się nie podoba).

Chodzi o to, że - ldd(lub ld?) Prawdopodobnie wykonuje niektóre z tych odnośników symboli, ale wypróbowałem odpowiednie strony podręcznika i nie widzę sposobu, aby „znaleźć” dowolny symbol z wiersza poleceń, bez podania jakiegoś pliku wykonywalnego jako pliku argument. Pytanie poboczne - czy istnieje sposób na wykorzystanie tych narzędzi?

Tak więc szukam narzędzia wiersza polecenia, które zachowałoby się jak (pseudokod):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

... gdzie nie określam żadnych katalogów do przeszukania - ale które również mogłyby obsługiwać, np. LD_PRELOADlub LD_LIBRARY_PATH; powiedz jeśli zrobię:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

... wtedy ustaliłbym, /path/to/mylib.sogdzie zdefiniowano dany symbol (biorąc pod uwagę, że taki symbol nie istniałby w standardowych bibliotekach) - w przeciwnym razie wyświetliłby „nie znaleziono”. W przeciwnym razie ./findsymbol --dumpallmoże wygenerować listę wszystkich dostępnych symboli i ich lokalizacji widzianych z danego środowiska (np. Konkretnej bashpowłoki).

Czy takie narzędzie istnieje w systemie Linux?

Odpowiedzi:


16

Ścieżki do wyszukiwania bibliotek zostaną wymienione w pliku /etc/ld.so.conf, zmiennej środowiskowej LD_LIBRARY_PATHi dowolnych RPATH zakodowanych w pliku binarnym ELF. Program lddpowie ci, jakie biblioteki załaduje określona aplikacja.

Gdy masz ciekawy symbol, możesz użyć programu nmdo zrzucenia symboli .oi .aplików oraz readelfdo zrzucenia symboli z .sodowolnego pliku wykonywalnego elfa.

Przykłady:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

I wreszcie, z tym tłem, oto twój święty Graal:

Biorąc pod uwagę symbol _ZN6Kopete6Global10PropertiesC2Ev, gdzie to jest?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

co daje:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

-lFlaga mówi szukać katalogi w /etc/ld.so.conforaz -sOkreśla symbol do znalezienia.


Jest to niekompletne: niektóre programy ładują biblioteki z katalogów specyficznych dla aplikacji.
Gilles „SO - przestań być zły”,

2
@Gilles scanelfpozwala określić określone katalogi do przeszukiwania i wspierać wyszukiwanie rekurencyjne, -rdzięki czemu można dostosować jego ścieżki wyszukiwania lub przeszukać cały system bez większych problemów. Na przykład scanelf -r -s SYMBOL /lib/* /usr/* /opt/*znajdzie większość miejsc, w których ukrywają się biblioteki.
Casey

7

W systemach GNU (podczas korzystania z dynamicznego linkera GNU libc) możesz uruchomić swój program jako:

LD_DEBUG=bindings kst2

Aby dowiedzieć się, gdzie symbole się kończą.


0

Natknąłem się na to wiele razy, próbując przenieść kod z jednego systemu Linux na inny. Zwykle po prostu szukam wszystkich standardowych katalogów. Nie mogłem znaleźć niczego googlującego. Oto krótki skrypt:

edt11x / findinsharedlibs

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.