Temukan di mana simbol perpustakaan bersama didefinisikan pada sistem hidup / daftar semua simbol yang diekspor pada suatu sistem

21

Pada dasarnya, ini adalah dua pertanyaan menjadi satu - karena jika saya dapat membuat daftar semua simbol yang diekspor dalam suatu sistem, bersama dengan jalur pustaka bersama mereka, maka saya dapat dengan mudah grepmenampilkannya.

Untuk simbol kernel, saya kira ini agak lebih mudah - karena kita dapat selalu cat /proc/kallsymsdan mendapatkan daftar semua simbol dari modul-modul yang dimuat dalam memori; kemudian sudo cat /proc/modulesakan memberikan daftar modul yang dimuat dengan alamatnya, tetapi bukan jalur darimana modul tersebut diambil (jika dibangun sebagai objek .ko yang terpisah dari pohon)

Misalnya, saya mencoba melacak program kstmenggunakan 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
...

... dan saya ingin tahu di mana ini _ZNK13QGraphicsItem10parentItemEvberada.

Jadi, apa yang harus dilakukan tentang simbol perpustakaan bersama? Membaca [bantuan gcc] Re: menemukan perpustakaan di mana simbol didefinisikan. ; Saya mencoba sesuatu seperti ini:

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

... tapi itu memberi saya masalah tambahan: Saya tidak benar-benar tahu semua jalur yang dipindai untuk perpustakaan bersama di sistem saya, jadi ketika saya pertama kali mencobanya find /lib ...tidak menemukan apa-apa; Saya menemukan bahwa menebak direktori ini menjengkelkan, sama seperti alternatifnya: memindai seluruh sistem file root dengan find... Dan juga, saya sepertinya menemukan * .so yang tidak dapat dibuka oleh nm(mungkin karena mereka adalah symlink?), Yang menampilkan sedikit pesan kesalahan (yang saya juga tidak suka).

Masalahnya adalah - ldd(atau ld?) Mungkin melakukan beberapa pencarian simbol ini, tetapi saya mencoba halaman manual masing-masing, dan saya tidak dapat melihat cara untuk "menemukan" simbol dari baris perintah, tanpa menyediakan semacam file yang dapat dieksekusi sebagai argumen. Pertanyaan sampingan - apakah ada cara untuk menggunakan alat ini untuk itu?

Jadi, apa yang saya cari alat baris perintah, yang akan berperilaku seperti (pseudocode):

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

... di mana saya tidak menentukan direktori yang akan dicari - tetapi yang juga akan menangani, misalnya LD_PRELOADatau LD_LIBRARY_PATH; katakan jika saya lakukan:

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

... maka saya akan mendapatkan di /path/to/mylib.somana simbol yang diberikan didefinisikan (mengingat bahwa simbol seperti itu tidak akan ada di perpustakaan standar) - dan akan menampilkan "tidak ditemukan" sebaliknya. Dan jika tidak, ./findsymbol --dumpalldapat menghasilkan daftar semua simbol yang tersedia dan lokasi mereka dilihat dari lingkungan tertentu (misalnya bashshell tertentu ).

Apakah alat seperti ini ada untuk Linux?

sdaau
sumber

Jawaban:

16

Path untuk mencari pustaka di akan terdaftar dalam file /etc/ld.so.conf, variabel lingkungan LD_LIBRARY_PATHdan setiap RPATH yang disandikan ke dalam biner ELF. Program lddakan memberi tahu Anda perpustakaan apa yang akan dimuat oleh aplikasi tertentu.

Setelah Anda memiliki simbol yang membuat Anda penasaran, Anda dapat menggunakan program ini nmuntuk membuang simbol .odan .afile dan readelfuntuk membuang simbol dari .soatau elf yang dapat dieksekusi.

Contoh:

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

Dan akhirnya, dengan latar belakang itu, inilah cawan suci Anda:

Diberi simbol _ZN6Kopete6Global10PropertiesC2Ev, di mana ini?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

yang menghasilkan:

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

The -lbendera mengatakan untuk dirs di mencari /etc/ld.so.confdan -smenspesifikasikan simbol untuk menemukan.

casey
sumber
Ini tidak lengkap: beberapa program memuat perpustakaan dari direktori khusus aplikasi.
Gilles 'SO- berhenti menjadi jahat'
2
@Gilles scanelfmemungkinkan Anda menentukan direktori spesifik untuk dicari dan mendukung penelusuran rekursif -rsehingga Anda dapat mengubah jalur pencariannya atau mencari seluruh sistem Anda tanpa terlalu banyak kesulitan. Misalnya scanelf -r -s SYMBOL /lib/* /usr/* /opt/*akan menemukan sebagian besar tempat perpustakaan bersembunyi.
casey
7

Pada sistem GNU (saat menggunakan GNU libc dynamic linker), Anda dapat menjalankan program Anda sebagai:

LD_DEBUG=bindings kst2

Untuk menemukan di mana simbol menyelesaikan.

Stéphane Chazelas
sumber
0

Saya telah mengalami ini beberapa kali, mencoba untuk mem-port code dari satu sistem Linux ke yang lain. Biasanya saya hanya mendapatkan semua direktori standar. Saya tidak dapat menemukan apa pun di Google. Jadi, inilah skrip cepat:

edt11x / findinsharedlibs

edt11x
sumber