Gprof: Как создать граф вызовов для функций в общей библиотеке, связанных с основной программой

Я работаю над средой Linux. У меня есть два исходных пакета C и train_train.

  • пакет поезда при компиляции генерирует libtrain.so
  • test_train ссылки на libtrain.so и генерирует исполняемый тестовый тест

Теперь я хочу сгенерировать граф вызовов, используя gprof, который показывает вызывающую последовательность функций в основной программе, а также внутри libtrain.so

Я компилирую и связываю оба пакета с параметром -pg, а уровень отладки - o0. После того, как я сделаю. /train -test, генерируется gmon.out. Тогда я делаю:

$ gprof -q ./train-test gmon.out

Здесь вывод показывает график вызовов функций в тестовом тесте, но не в libtrain.so

В чем может быть проблема?

Ответ 1

gprof не будет работать, вам нужно использовать sprof. Я нашел эти ссылки полезными:

Резюме из 2-й ссылки:

  • Скомпилируйте вашу общую библиотеку (libmylib.so) в режиме отладки (-g). Нет -pg.
  • экспортировать LD_PROFILE_OUTPUT = `pwd`
  • export 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, не уверен) - в противном случае вы не получите никаких предупреждений.

Ответ 2

Я загружаю свою библиотеку из Python и не имел никакого счастья с sprof. Вместо этого я использовал oprofile, который был в репозиториях Fedora, по крайней мере:

operf --callgraph /path/to/mybinary

Дождитесь завершения вашего приложения или сделайте Ctl-c, чтобы остановить профилирование. Теперь давайте сгенерируем резюме профиля:

opreport --callgraph --symbols

См. документацию для ее интерпретации. Это вроде беспорядок. В сгенерированном отчете каждый символ указан в отдельном блоке. Главный символ блока - тот, который не имеет отступов. Элементы над ним - это функции, которые вызывают эту функцию, а те, что ниже нее, - это вещи, которые вызываются ею. Проценты в приведенном ниже разделе - это относительное количество времени, затрачиваемого на эти вызовы.

Ответ 3

Если вы не в Linux (например, я на Solaris), вам просто не повезло, так как там нет sprof. Если у вас есть источники вашей библиотеки, вы можете решить свою проблему, связав статическую библиотеку и сделав вместо нее свой профилирующий двоичный код. Другой способ, с помощью которого я могу отслеживать вызовы в разделяемые библиотеки, - это использовать truss. С помощью опции -u [!]lib,...:[:][!]func, ... можно получить хорошую картину истории вызовов прогона. Это не совсем то же самое, что и профилирование, но может быть очень полезно в некоторых сценариях.