Есть ли способ сказать gdb, чтобы дождаться начала процесса и привязки к нему?

У меня есть процесс, который вызывается другим процессом, который вызывается другим процессом и т.д. ad nauseum. Это дочерний процесс в длинной цепочке инструментов.

Этот процесс сбой.

Я хотел бы поймать этот процесс в gdb, чтобы понять, почему он сбой. Однако, единственный способ, о котором я могу думать, это:

  • запустите исходный родительский процесс в командной строке.
  • poll ps -C <name process I want to catch> и получить PID.
  • запуск gdb, прикрепленный к этому процессу PID.

Это громоздко, но обычно выполняет эту работу. Проблема в том, что текущий сбой выполняется очень быстро, и к моменту захвата PID и запуска gdb он уже прошел точку отказа.

Я хотел бы запустить gdb и вместо:

(gdb) attach <pid>

Я хотел бы сделать:

(gdb) attach <process name when it launches>

Есть ли способ сделать это?


Я использую gdb 7.1 для linux

Ответ 1

Вот мой script, называемый gdbwait:

#!/bin/sh
progstr=$1
progpid=`pgrep -o $progstr`
while [ "$progpid" = "" ]; do
  progpid=`pgrep -o $progstr`
done
gdb -ex continue -p $progpid

Использование:

gdbwait my_program

Конечно, это может быть написано лучше, но синтаксис оболочки Bourne script для меня болезнен, поэтому, если он работает, я оставляю его в покое.:) Если новый процесс запускается и умирает слишком быстро, добавьте 1 секунду задержки в свою собственную программу для отладки...

Ответ 2

В Mac OS X вы можете использовать:

(gdb) attach --waitfor <process-name>

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

Примечания к выпуску GDB для Mac OS X v10.5 Семена WWDC

Ответ 3

Вы можете подключиться к родительскому процессу и установить дочерний режим дочернего режима. Это приведет к распаковке дочернего процесса gdb вместо родителя после форкирования. Также полезно использовать catch fork. Это приведет к остановке gdb после каждой вилки. См. docs.

Ответ 4

Не совсем то, что вы ожидаете, но это может помочь вам в отладке.

valgrind --trace-children=yes your_program

будет проверять и печатать ошибки памяти у всех дочерних элементов процесса, с трассировкой стека и некоторыми подробностями об ошибке (например, в случае двойного освобождения, вы получите трассировку стека первого бесплатного).

Кроме того, вы можете заставить процесс сбоя генерировать дамп ядра и отлаживать эту посмертную ошибку. Подробнее см. .

Ответ 5

У меня возникла аналогичная проблема с тем, что я пытаюсь отлаживать, и я придумал решение, использующее ldpreload, но, увидев ответ Joeys, я думаю, что сначала попробую. В случае, если это полезно для всех, но здесь идея:

Создайте библиотеку LD_PRELOAD, чтобы подключить вызовы exec * (есть много руководств о том, как это сделать, но если я это сделаю, я обновлю ответ с кодом), проверьте путь, используемый при прохождении через exec * call, если это наша цель, то вывести сообщение с PID на stderr и перейти в бесконечный цикл (со сном, чтобы избежать массового использования ЦП). Затем вы можете подключиться с помощью gdb и изменить регистр, используемый в цикле, для продолжения выполнения.

Это может быть связано с некоторыми встроенными ASM, чтобы убедиться, что компилятор не оптимизирует бесконечный цикл таким образом, что это затрудняет выход из него. Более красноречивым способом сделать это было бы найти способ обнаружить, что gdb подключен, а затем вызвать точку останова ( "asm (" int3 ")", должен делать трюк на последнем).