Найти, где находится символ общей библиотеки, определенный в действующей системе / перечислить все символы, экспортированные в систему

21

По сути, это два вопроса в одном - потому что, если я смогу перечислить все символы, экспортируемые в систему, вместе с их общим путем к библиотеке, я мог бы просто получить grepтакой вывод.

Для символов ядра, я думаю, это несколько проще - потому что мы всегда можем cat /proc/kallsymsполучить список всех символов этих модулей, загруженных в память; затем sudo cat /proc/modulesвыдаст список загруженных модулей с их адресами, но не с указанием путей, откуда были загружены модули (если они построены как отдельные объекты .ko вне дерева)

Например, я пытаюсь отследить программу, kstиспользуя 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
...

... и я хотел бы знать, где это _ZNK13QGraphicsItem10parentItemEvнаходится.

Итак, что делать с символами разделяемой библиотеки? Чтение [gcc-help] Re: поиск библиотеки, в которой определен символ. ; Я попробовал что-то вроде этого:

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

... но это доставляет мне дополнительные проблемы: я действительно не знаю всех путей, которые сканируются для общих библиотек в моей системе, поэтому, когда я впервые попробовал, find /lib ...он ничего не нашел; Я нахожу это предположение о каталогах утомительным, равно как и альтернатива: сканирование всей корневой файловой системы с find... А также, я, кажется, поражаю * .so, которые не могут быть открыты nm(возможно, потому что они являются символическими ссылками?), Которые вывести довольно много сообщений об ошибках (которые мне тоже не нравятся).

Дело в том, что ldd(или ld?), Вероятно, выполняет некоторые из этих поисков символов, но я попробовал соответствующие страницы man, и я не могу найти способ «найти» какой-либо символ из командной строки, не предоставив некоторый исполняемый файл в виде аргумент. Дополнительный вопрос - есть ли способ использовать эти инструменты для этого?

Итак, что я ищу инструмент командной строки, который будет вести себя примерно так (псевдокод):

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

... где я не указываю никаких каталогов для поиска - но которые также обрабатывают, например, LD_PRELOADили LD_LIBRARY_PATH; сказать, если я делаю:

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

... тогда я бы получил, /path/to/mylib.soгде был определен данный символ (учитывая, что такой символ не существовал бы в стандартных библиотеках) - и вывел бы «не найдено» в противном случае. Иначе, ./findsymbol --dumpallмог бы произвести список всех доступных символов и их местоположений, видимых из данной среды (например, определенной bashоболочки).

Существует ли такой инструмент для Linux?

sdaau
источник

Ответы:

16

Пути для поиска библиотек будут перечислены в файле /etc/ld.so.conf, переменной среды LD_LIBRARY_PATHи любых RPATH, закодированных в двоичном файле ELF. Программа lddскажет вам, какие библиотеки будет загружать конкретное приложение.

Если у вас есть интересующий вас символ, вы можете использовать программу nmдля выгрузки символов .oи .aфайлов, а также readelfдля выгрузки символов из .soисполняемого файла elf или любого другого.

Примеры:

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

И, наконец, с этим фоном, вот ваш святой Грааль:

Учитывая символ _ZN6Kopete6Global10PropertiesC2Ev, где это?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

который дает:

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

-lФлаг говорит искать каталоги в /etc/ld.so.confи -sопределяет , символ для поиска.

Casey
источник
Это неполно: некоторые программы загружают библиотеки из каталогов конкретных приложений.
Жиль "ТАК - перестань быть злым"
2
@Gilles scanelfпозволяет вам указывать конкретные каталоги для поиска и поддерживать рекурсивное кэширование, -rчтобы вы могли без проблем настраивать его пути поиска или выполнять поиск по всей вашей системе. Например scanelf -r -s SYMBOL /lib/* /usr/* /opt/*, найдет большинство мест, которые скрывают библиотеки.
Кейси
7

В системах GNU (при использовании динамического компоновщика GNU libc) вы можете запустить вашу программу как:

LD_DEBUG=bindings kst2

Чтобы найти, где символы разрешают.

Стефан Шазелас
источник
0

Я сталкивался с этим несколько раз, пытаясь перенести код из одной системы Linux в другую. Обычно я просто в конечном итоге grep'ing все стандартные каталоги. Я не мог найти что-нибудь гуглить. Итак, вот быстрый скрипт:

edt11x / findinsharedlibs

edt11x
источник