Работа с процессами и потоками исполнения

В отладчике GDB для работы с процессами используются объекты, которые называются инфериорами (англ. inferiors). Процесс каждой программы, которую нужно отладить, должен быть привязан к отдельному инфериору. Переключение между инфериорами соответствует переключению фокуса отладки в контекст другого процесса. Отладочные символы для программы, которую требуется отладить, нужно загружать после переключения на инфериор, который привязан к процессу этой программы.

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

GDB-команды для работы с инфериорами

Для работы с инфериорами нужно использовать следующие GDB-команды:

Настройка обработки событий жизненного цикла процессов

GDB-сервер ядра сообщает отладчику GDB о наступлении следующих событий:

  1. создание дочернего процесса;
  2. запуск начального потока исполнения дочернего процесса;
  3. завершение процесса.

Отладчик GDB обрабатывает событие 1 только в том случае, если существует инфериор, привязанный к родительскому процессу. Для обработки события 2 необходимо, чтобы отладчик GDB предварительно обработал событие 1 при создании дочернего процесса. При этом событие 2 обрабатывается, даже если родительский процесс уже отвязан от инфериора, например, по причине завершения.

Чтобы настроить обработку событий 1 и 2, нужно использовать следующие GDB-команды:

Рекомендуется настроить обработку событий 1 и 2 следующим образом:

set follow-fork-mode parent

set follow-exec-mode same

set detach-on-fork off

Такая конфигурация обеспечивает обработку событий 1 и 2 отладчиком GDB следующим образом:

Обработку отладчиком GDB события 2 можно использовать для остановки исполнения программы до передачи управления функции main(), чтобы не применять бесконечный цикл.

Чтобы исполнение программы остановилось при наступлении события 2, нужно использовать следующую GDB-команду:

catch exec

Эта GDB-команда обеспечивает остановку исполнения каждого дочернего процесса, при создании которого было обработано событие 1. Чтобы выполнить остановку исполнения отдельных процессов, нужно использовать следующую GDB-команду:

monitor exec [<имя процесса 1>][, <имя процесса 2>]...

Последующий вызов этой GDB-команды отменяет предыдущий, а ее вызов без параметров означает остановку каждого дочернего процесса, при создании которого было обработано событие 1.

Событие 3 обрабатывается отладчиком GDB только в том случае, если созданы инфериоры, привязанные к завершившимся процессам. При обработке этого события отладчик GDB отвязывает инфериор от завершившегося процесса. Обработку события 3 не требуется настраивать.

GDB-команды для работы с потоками исполнения

Чтобы вывести список потоков исполнения, которые содержатся в процессах, привязанных к инфериорам, нужно выполнить следующую GDB-команду:

info threads

Текущий поток исполнения отмечается символом *. (Контекст текущего потока исполнения находится в фокусе отладки.)

Чтобы перейти в контекст другого потока исполнения, нужно выполнить следующую GDB-команду:

thread <значение Id, полученное вызовом GDB-команды info threads>

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

В начало