gprof: как создать граф вызовов для функций в разделяемой библиотеке, связанной с основной программой
Я работаю в среде Linux. У меня есть два исходных пакета 'C' train и test_train.
- пакет train при компиляции генерирует libtrain.so
- test_train ссылается на libtrain.so и генерирует исполняемый train-test
Теперь я хочу сгенерировать граф вызовов с помощью gprof, который показывает последовательность вызова функций в основной программе, а также функции внутри libtrain.so
Я компилирую и связываю оба пакета с опцией -pg, а уровень отладки равен o0. После того, как я сделаю./train-test, генерируется gmon.out. Тогда я делаю:
$ gprof -q ./train-test gmon.out
Здесь вывод показывает график вызова функций в train-test, но не в libtrain.so
В чем может быть проблема?
3 ответа
gprof
не сработает, нужно использовать sprof
вместо. Я нашел эти ссылки полезными:
- Как использовать спроф?
- http://greg-n-blog.blogspot.com/2010/01/profiling-shared-library-on-linux-using.html
Резюме со 2-й ссылки:
- Скомпилируйте свою общую библиотеку (libmylib.so) в режиме отладки (-g). Нет-JP.
- export LD_PROFILE_OUTPUT = `pwd`
- экспорт LD_PROFILE = libmylib.so
- rm -f $ LD_PROFILE.profile
- выполнить вашу программу, которая загружает libmylib.so
- sprof PATH-TO-LIB / $ LD_PROFILE $ LD_PROFILE.profile -p> log
- Смотрите журнал.
Я обнаружил, что на шаге 2 это должен быть существующий каталог - в противном случае вы получите полезное предупреждение. И на шаге 3 может потребоваться указать библиотеку как libmylib.so.X
(может быть даже .X.Y
, не уверен) - иначе вы не получите никакого предупреждения.
Я загружаю свою библиотеку из Python и мне не повезло с sprof
, Вместо этого я использовал oprofile
, который был в репозиториях Fedora, по крайней мере:
operf --callgraph /path/to/mybinary
Подождите, пока ваше приложение не завершится или выполните Ctl-c, чтобы прекратить профилирование. Теперь давайте сгенерируем резюме профиля:
opreport --callgraph --symbols
Смотрите документацию, чтобы интерпретировать это. Это вроде беспорядок. В сгенерированном отчете каждый символ указан в отдельном блоке. Главный символ блока - это тот, который не имеет отступа. Элементы над ним - это функции, вызывающие эту функцию, а под ней - те, которые ей вызываются. Проценты в следующем разделе представляют собой относительное количество времени, которое он провел в этих вызываемых.
Если вы не в Linux (как я в Solaris), вам просто не повезло, так как нет sprof
там. Если у вас есть источники вашей библиотеки, вы можете решить свою проблему, связав статическую библиотеку и сделав вместо нее свой бинарный файл профилирования. Еще один способ, которым мне удается отследить вызовы к общим библиотекам, заключается в использовании truss
, С возможностью -u [!]lib,...:[:][!]func, ...
можно получить хорошее представление об истории вызовов бега. Это не совсем то же самое, что профилирование, но может быть очень полезным в некоторых сценариях.