Список всех вызовов функций, выполненных в приложении - PullRequest
20 голосов
/ 04 марта 2012

Как мы можем перечислить все функции, вызываемые в приложении. Я пытался использовать GDB, но его список следов только до вызова основной функции.

Мне нужен более глубокий список, т.е. список всех функций, вызываемых основной функцией, и функции, вызываемой из этих вызываемых функций и т. Д.

Есть ли способ получить это в GDB? Или могли бы вы дать мне совет, как это получить?

Ответы [ 4 ]

22 голосов
/ 04 марта 2012

Как мы можем перечислить все функции, вызываемые в приложении

Для любого приложения реалистичного размера этот список будет содержать тысячи записей, что, вероятно, сделает его бесполезным.

Вы можете найти все функции , определенные (но не обязательно вызванные) в приложении с помощью команды nm, например,

nm /path/to/a.out | egrep ' [TW] '

Вы также можете использовать GDB для установки точки останова для каждой функции:

(gdb) set logging on     # collect trace in gdb.txt
(gdb) set confirm off    # you wouldn't want to confirm every one of them
(gdb) rbreak .           # set a breakpoint on each function

Как только вы продолжите, вы достигнете точки останова для каждой вызванной функции. Используйте команды disable и continue для продвижения вперед. Я не верю, что есть простой способ автоматизировать это, если только вы не хотите использовать скрипты Python.

Уже упоминалось, gprof - еще один хороший вариант.

9 голосов
/ 04 марта 2012

Вы хотите график звонков. Инструмент, который вы хотите использовать, это не GDB, а gprof. Вы компилируете свою программу с -pg и затем запускаете ее. Когда он запускается, будет создан файл gmon.out. Затем вы обрабатываете этот файл с помощью gprof и наслаждаетесь выводом.

6 голосов

запись истории вызовов функций

https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html

Это должно быть большим аппаратным ускорением возможность, если вы один изнесколько человек (2015) с процессором, который поддерживает Intel Processor Tracing (Intel PT, intel_pt in /proc/cpuinfo).

Документация GDB утверждает, что он может производить вывод, подобный:

(gdb) list 1, 10
1   void foo (void)
2   {
3   }
4
5   void bar (void)
6   {
7     ...
8     foo ();
9     ...
10  }
(gdb) record function-call-history /ilc
1  bar     inst 1,4     at foo.c:6,8
2    foo   inst 5,10    at foo.c:2,3
3  bar     inst 11,13   at foo.c:9,10

Перед его использованием необходимо выполнить:

start
record btrace

, в котором сбой невозможного ЦП:

 Target does not support branch tracing.

Поддержка ЦП дополнительно обсуждается в: Как запустить запись истории команд и истории вызовов функций в GDB?

Связанные темы:

Для встраиваемых систем вы также рассматриваете JTAG и вспомогательное оборудование, напримерARM DSTREAM , но поддержка x86 выглядит не очень хорошо: отладка ядра x86 с использованием аппаратного отладчика

3 голосов
/ 02 сентября 2013

Этот вопрос может потребовать уточнения, чтобы выбрать между тем, что в настоящее время являются 2 ответами. Зависит от того, что вам нужно:

1) Вам необходимо знать, сколько раз каждая функция вызывается в формате прямого списка / графика функций, соответствующих количеству вызовов. Это может привести к неоднозначным / неубедительным результатам, если ваш код не является процедурным (то есть функции, вызывающие другие функции в разветвленной структуре без неоднозначности того, что вызывает что). Это базовая функциональность gprof, требующая перекомпиляции с флагом -pg.

2) Вам нужен список функций в том порядке, в котором они были вызваны, это зависит от вашей программы, которая является наилучшей / выполнимой опцией: а) Если ваша программа запускается и завершается без ошибок времени выполнения, вы можете использовать для этой цели gprof. б) Опция ELSE, описанная выше с использованием dbg с регистрацией и точками останова, является опцией, которую я изучил после прочтения этого.

3) Вам необходимо знать не только порядок, но, например, аргументы функции для каждого вызова. Моя текущая работа - это моделирование в физике переноса частиц, так что это было бы АБСОЛЮТНО полезно для отслеживания того, откуда поступают аномальные результаты ... то есть, когда аргументы, передаваемые вокруг, перестают иметь смысл. Я полагаю, что один из способов сделать это - это вариация того, что делал Employed Russian, за исключением использования следующего:

(gdb) info args

Регистрация результатов этой команды с каждой точкой останова (устанавливается при каждом вызове функции) дает аргументы текущей функции.

...