Публикации Разное

Отладчик GNU GDB

19.04.2005
Илья Аввакумов

Введение

Откровенно говоря, программа GNU GDB довольно многофункциональная. Пошаговая от­лад­ка — лишь одна из ее возможностей. В этой статье я попытался описать те лишь команды GDB, которые позволяют проводить удобную пошаговую отладку программ, на­пи­сан­ных на Free Pascal.

Чтобы программу можно было отлаживать, она должна быть откомпилирована с ключом -g.

Поскольку GDB ориентирован не на Pascal, а на C и C++, то использование GDB для от­лад­ки Pascal-программ иногда сопряжено с неудобствами.

Приведу список подводных камней, обнаруженных мною и разработчиками Free Pascal (пе­ре­чис­лен­ных в user's manual).

  1. Отладочная информация в Free Pascal генерируется в верхнем регистре. Поэтому имена всех переменных, процедур, функций при использовании GDB должны указываться БОЛЬШИМИ БУКВАМИ.
  2. GDB не воспринимает тип extended (ведь в C такого типа нет). Обойти эту неприятность можно, если, например, включить в код такие строки
    ...
    type
    {$IFDEF DEBUG}
    dbl = double;
    {$ELSE}
    dbl = extended;
    {$ENDIF}
    ...

    var x : dbl;
    ...
  3. К элементам многомерных массивов нужно обращаться в C-шной манере, а именно, команда
    (gdb) print A[1,1]
    выдаст первую строку массива A. Для просмотра требуемого элемента следует писать
    (gdb) print A[1][1]
  4. GDB не воспринимает множества.
  5. Есть трудности с поддержкой объектов (см. user's manual за подробностями).
  6. Есть трудности с глобально переопределенными функциями. (за подробностями см. user's manual).
  7. При отладке процедур, функций, расположенных в разных файлах, часто возникает несоответствие — смещение строк. Та строка, которую GDB показывает текущей, таковой не является, а текущая расположена строк эдак на двадцать выше. Это приводит к большим неудобствам при пошаговой отладке. Я для себя сделал из этого такую мораль — хоть GDB и позволяет отлаживать процедуры, описанные в разных файлах, но лучше этой возможностью не пользоваться, а на время отладки все вызываемые процедуры, работа которых вас заинтересует, помещать в одном файле.

Все примеры отлаживались с использованием GNU GDB 5.0.


Запуск отладчика GDB

gdb [опции] [имя_файла | ID процесса]

После запуска видим "nice GDB logo" (если это почему-то раздражает, то опция -q поз­во­ля­ет не выводить это введение с ин­фор­ма­ци­ей об авторских правах и прочая). В следующей стро­ке приглашение
(gdb)
ждет ввода команды.

Ниже приводится краткий перечень команд GDB.

Краткую справку о любой команде можно получить, введя
(gdb) help [имя_команды, можно краткое]

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


Команда file

(gdb) file <имя исполняемого файла, который подлежит отладке>


Для того, чтобы пролистать содержимое исходника, используйте команду list (сокращенно l; большая часть наиболее полезных ко­манд имеют сокращения). При этом под­ра­зу­ме­ва­ет­ся, что исходник расположен в том же каталоге, что и исполняемый файл. Как правило, так оно и есть.

Команда list (сокращенно l)

Пролистывает 10 строк вниз, начиная с текущей. Для пролистывания вверх следует набрать

(gdb) list -


Команда run (сокращенно r)

Запускает отлаживаемую программу под GDB. Если требуется, то после команды можно ука­зать список аргументов программы. Так­же допускается перенаправление потоков ввода и вы­во­да в другие файлы, например

(gdb) run > outfile

Если никаких точек останова не определено, то программа выполняется тихо, при этом нам со­об­ща­ет­ся:

(gdb) run
Starting program: test
Program exited normally.
(gdb)

Если же отладчик встречает точку останова, он выдает ее номер, адрес и дополнительную ин­фор­ма­цию — текущую строку, имя про­це­ду­ры, и т.п.

(gdb) r
Breakpoint 1, main () at test.pp:3
Current language: auto; currently pascal
3 x := x + 1;
(gdb)

И ожидает ввода команды.


Остановка отладки программы

Команда kill (k). Следует запрос

(gdb) kill
Kill the program being debugged? (y or n) y
(gdb)

Здесь введено y (то есть "да"), и отладка программы прекращается. Командой run ее можно на­чать заново, при этом все точки ос­та­но­ва (breakpoints), точки просмотра (watchpoints) и точ­ки отлова (catchpoints) сохраняются.


Выход из отладчика

Команда quit (q).

(gdb) q
[avva@localhost home]$

Точки останова

Информацию о командах этого раздела можно получить, введя
(gdb) help breakpoints

Точки останова — такие, когда GDB приостанавливает выполнение программы. Как уже упо­ми­на­лось, имеется 3 типа точек ос­та­но­ва:

  1. Breakpoints — точка останова как таковая. Остановка происходит, когда выполнение доходит до определенной строки, адреса или процедуры/функции.
  2. Watchpoints — точка просмотра. Выполнение программы приостанавливается, если программа обратилась к определенной переменной — либо считала ее значение, либо изменила его.
  3. Catchpoints — точка отлова. Приостановка происходит при определенном событии (например, получение сигнала). Я не буду касаться точек останова этого типа.

Определение точек останова


Breakpoint

Команда break
(gdb) break [аргумент]
или, сокращенно
(gdb) b [аргумент]
определяет точку останова. В качестве аргумента может выступать

  • номер строки. Остановка произойдет при достижении строки программы с этим номером. То, что написано в самой строке, выполняться не будет. Например
    (gdb) b 394 Breakpoint 1 at 0x805a650: file maeq.pas, line 394.
  • имя процедуры (функции). Отладчик зайдет в эту процедуру и остановит выполнение программы. NB!! Имя процедуры (функции) должно быть указано БОЛЬШИМИ БУКВАМИ. Приведу пример:
    (gdb) b CALC Breakpoint 2 at 0x7657c7a: file maeq.pas, line 26.
  • если вызвать команду break без аргументов, то точка останова поставится на текущей строке.
  • также можно явно указывать адрес точки останова (перед адресом надо поставить знак *). Приведу лишь пример для полноты описания:
    (gdb) b *0x805a650 Breakpoint 3 at 0x805a650: file maeq.pas, line 394.

Допускается использование нескольких точек останова на одной строке (функции, адресе).


Watchpoint

Существуют различные виды точек просмотра, и задаются они различными командами:

  • команда watch (сокращенно wa)
    (gdb) wa <переменная>
    Выполнение программы приостанавливается всякий раз, когда значение указанной переменной изменяется.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.
     
  • команда rwatch (сокращенно rw)
    (gdb) rw <переменная>
    Выполнение приостанавливается всякий раз, когда программа считывает значение указанной переменной.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.
     
  • команда awatch (сокращенно aw)
    (gdb) aw <переменная>
    Выполнение приостанавливается всякий раз, когда программа обращается к указанной переменной, как для считывания, так и для записи.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.

Замечу от себя, что команды rwatch и awatch у меня почему-то капризничают — часто не ус­та­нав­ли­ва­ют точки просмотра на пе­ре­мен­ную. Зато команда watch работала всегда.


Управление точками останова

Информацию о всех установленных точках останова можно вывести командой info.

Команда info имеет много возможностей, но в данном случае воспользуемся лишь сле­дую­щим ее форматом:
(gdb) info breakpoints
или, кратко
(gdb) i b

Выводится подробная информация о всех точках останова (как breakpoints, так и watch­points), включающая - номер - breakpoint или watchpoint - активность - сколько раз прог­рам­ма натыкалась на эту точку - иные характеристики, значение которых мне не со­всем понятно

Если какая-то точка останова не нужна, то ее можно сделать неактивной с помощью ко­ман­ды disable:

(gdb) disable breakpoint <номер этой точки>

Обратно, деактивированная точка останова активируется командой enable:

(gdb) enable breakpoint <номер этой точки>

Статус точки останова — активна она или нет, легко обозреть той же командой info.

Если же точка останова не требуется вообще, то она может быть удалена насовсем.

(gdb) delete breakpoint [номер точки]

а короче

(gdb) d b [номер точки]

Ввод этой команды без аргумента удалит ВСЕ точки останова.


Возобновление выполнения, пошаговая отладка

Информацию о командах этого раздела можно получить, введя

(gdb) help running

Команда continue (c)

(gdb) с [аргумент]

Продолжает выполнение остановленной программы. Выполнение будет происходить, пока сно­ва не встретится точка останова. В ка­чест­ве аргумента может использоваться целое чис­ло N. Это укажет отладчику проигнорировать (N-1) точку останова (вы­пол­не­ние остановится на N-ой).


Команда step (s)

(gdb) s [аргумент]

Аналог действия клавиши F7 (Trace into) в IDE. Происходит выполнение программы до тех пор, пока не будет достигнута сле­дую­щая строка ее кода. При указании аргумента — це­ло­го чис­ла N, отладчик выполняет команду step N раз (если не останавливает вы­пол­не­ние из-за точек останова или по иным причинам).


Команда next (n)

(gdb) n [аргумент]

Аналог действия клавиши F8 (Step over) в IDE. В отличие от step вызов процедуры счи­та­ет­ся единой инструкцией (не заходит в вы­зы­вае­мые процедуры, функции). Аргумент N ра­бо­та­ет так же, как и для step.


Команда finish (fin)

(gdb) fin

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


Команда until (u)

Производит выполнение программы до тех пор, пока не будет достигнута строка с номером, боль­шим текущего. Команду until удоб­но применять при отладке циклов. Остановка про­и­зой­дет также, если программа при выполнении цикла выйдет из текущей про­це­ду­ры, функ­ции.


Команда stepi (si)

(gdb) si [аргумент]

Действие подобно step, но выполняется не строка, а ровно одна инструкция в этой строке прог­рам­мы. Аргумент N нужен, если тре­бу­ет­ся выполнить N инструкций.


Команда nexti (ni)

(gdb) ni [аргумент]

Аналогична stepi, но вызовы процедур трактуются как одна инструкция.


Управление состоянием (просмотр, изменение) переменных при отладке

Информацию о командах этого раздела можно получить, введя

(gdb) help data

Команда print (p)

(gdb) print <выражение>

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

Часто требуется отслеживать значения нескольких переменных. Чтобы не утруждать себя мно­го­крат­ным вводом команды print, ис­поль­зуй­те команду display.


Команда display

(gdb) display [аргумент]

В качестве аргумента обычно указывают переменную или выражение. При этом указанная пе­ре­мен­ная (выражение) занесется в дис­плей, то есть станет выводиться при каждой ос­та­нов­ке программы (при попадании на точку останова, при пошаговом вы­пол­не­нии командами step и next, etc). Если вызвать display без аргументов, то GDB выдаст значения всех пе­ре­мен­ных (вы­ра­же­ний), занесенных в дисплей.

Управление списком этих переменных осуществляется аналогично точкам останова. А имен­но, команда info display

(gdb) info display

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

(gdb) disable display <номер переменной в списке дисплея>

или активирована заново

(gdb) enable display <номер переменной в списке дисплея>

Удаление переменной из списка дисплея производится командой delete или командой undisplay. Так, команда

(gdb) delete display [номер переменной в списке дисплея]

делает то же, что и

(gdb) undisplay [номер переменной в списке дисплея]

Опять-таки, если не указать номер переменной, то очистится весь список отображаемых пе­ре­мен­ных.


Изменение значения переменной

И последнее. Изменение значения переменной на другое можно, например, произвести с по­мощью команд set или print.

(gdb) set <оператор присваивания>
(gdb) print <оператор присваивания>

Например,

(gdb) whatis x
TYPE = WORD
(gdb) p x
$1 = 1
(gdb) set x:=2
(gdb)

При использовании set присваивание происходит "тихо". То же самое можно сделать, но с по­мощью команды print.

Например,

(gdb) p x
$2 = 2
(gdb) p x:=x-2
$3 = 0
(gdb)

При этом, как видно, выводится новое значение переменной.

Вот и все.

Удачной отладки!

Актуальные версии
FPC3.0.0release
Lazarus1.6release
MSE4.2release
fpGUI1.4.1release
наши спонсоры ;)
Банк уралсиб использованием платежного терминала.
Самая свежая информация купить дом киевская область на нашем сайте.