Сделайте так, чтобы GDB печатал поток управления функциями, как они называются - PullRequest
17 голосов
/ 23 ноября 2008

Как мне сделать функции печати GDB интересными при их вызове, с отступом в зависимости от того, как глубоко они в стеке?

Я хочу иметь возможность сказать что-то вроде (выдуманное):

(gdb) trace Foo* Bar* printf

И пусть GDB напечатает все функции, начинающиеся с Foo или Bar, как они называются. Вроде как в gnu cflow, за исключением того, что используются символы отладки и только те функции печати, которые действительно вызываются, а не все возможные потоки вызовов.

Инструменты, которые не помогут, включают cachegrind, callgrind и oprofile, которые упорядочивают результаты, по которым функции вызывались чаще всего. Мне нужно сохранить порядок звонков.

Подстановочный знак (или его эквивалент) имеет важное значение, так как есть много функций Foo и Bar. Хотя я бы согласился на запись абсолютно всех функций. Или, возможно, сказать GDB записать все функции в конкретной библиотеке.

У некоторых мастеров GDB должен быть скрипт для этой обычной работы!

Ответы [ 5 ]

8 голосов
/ 01 октября 2009

В вашем случае я бы обратился к команде define в gdb, которая позволяет вам определить функцию, которая может принимать до 10 аргументов.

Вы можете передать имена функций для «трассировки» в качестве аргументов определенной вами функции или записать их все в самой функции. Я бы сделал что-то вроде следующего

define functiontrace
if $arg0
    break $arg0
    commands
        where
        continue
        end
    end

if $arg1
...

Аргументы пользовательской функции в gdb называются $ arg0- $ arg9. В качестве альтернативы, вы можете просто записать каждую функцию, которую хотите отследить в функции, вместо использования $ arg0-9.

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

3 голосов
/ 30 января 2013

Есть rbreak cmd, принимающий регулярное выражение для установки точек останова. Вы можете использовать:

(gdb) rbreak Foo.*
(gdb) rbreak Bar.*
(gdb) break printf

См. для получения подробной информации о точках останова.

Затем используйте commands, чтобы напечатать каждую функцию при вызове. Например. пусть α = номер последней точки останова (вы можете проверить это с помощью i br, если вы пропустили) , затем выполните:

(gdb) commands 1-α
Type commands for breakpoint(s) 1-α, one per line.
End with a line saying just "end".
>silent
>bt 1
>c
>end
(gdb) 

Некоторое уточнение: silent подавляет ненужные информационные сообщения, bt 1 печатает последний кадр обратного следа (т.е. это текущая функция) , c - это сокращение для continue, чтобы продолжить выполнение, а end - это просто разделитель списка команд.

NB : если вы отслеживаете функции библиотеки, вы можете дождаться загрузки lib. Например. установите перерыв на main или любую другую функцию, запустите приложение до этой точки и только затем установите нужные вам точки останова.

2 голосов
/ 14 июля 2009

Используйте правильный инструмент для работы;)

Как автоматически напечатать следующие N выполненных строк в GDB?

1 голос
/ 23 ноября 2008

Вы видели отличный ответ Литба на аналогичный пост здесь ?

Он использует readelf, чтобы получить интересные символы, команды GDB, чтобы получить трассировку, и awk, чтобы склеить все это.

По сути, вам нужно изменить его командный скрипт gdb, чтобы убрать глубину 1 из обратной трассировки, чтобы увидеть стек и отфильтровать определенные функции, и переформатировать вывод сценарием awk / python / (...) для представления это как дерево. (Признаюсь, мне сейчас лень это делать ...)

0 голосов
/ 23 ноября 2008

Вы можете позвонить gdb в пакетном режиме (используя опцию -x), разбить, где вам нужно, и попросить обратную трассировку (bt), затем отфильтровать результат, используя grep или egrep.

Отступы сложнее, однако вывод bt упорядочен, поэтому у вас есть текущая функция вверху трассы и main в самом низу.

Итак, вы создаете файл с командами:

br <function name where to break>
run
bt
kill
quit

затем запустите gdb <program> -x<command file>

Фильтровать строки, начинающиеся с #<digit> - вы получите трассировку стека.

...