Книга: Linux программирование в примерах

15.3.1. Запуск GDB

15.3.1. Запуск GDB

Основное использование следующее:

gdb [опции][исполняемый файл [имя файла дампа]]

Здесь исполняемый файл является отлаживаемой программой. Имя файла дампа, если оно имеется, является именем файла core, созданном при завершении программы операционной системой с созданием снимка процесса. Под GNU/Linux такие файлы (по умолчанию) называются core.pid[167], где pid является ID процесса запущенной программы, которая была завершена. Расширение pid означает, что в одном каталоге могут находиться несколько дампов ядра, что бывает полезно, но также занимает дисковое пространство!

Если вы забыли указать в командной строке имена файлов, для сообщения GDB имени исполняемого файла можно использовать 'file исполняемый-файл', а для имени файла дампа — 'core-file имя-файла-дампа'.

При наличии дампа ядра GDB указывает место завершения программы. Следующая программа, ch15-abort.c, делает несколько вложенных вызовов функций, а затем намеренно завершается посредством abort(), чтобы создать дамп ядра:

/* ch15-abort.c --- создает дамп ядра */
#include <stdio.h>
#include <stdlib.h>
/* recurse --- создание нескольких вызовов функций */
void recurse(void)
{
 static int i;
 if (++i == 3)
  abort();
 else
  recurse();
}
int main(int argc, char **argv)
{
 recurse();
}

Вот небольшой сеанс GDB с этой программой:

$ gcc -g ch15-abort.c -o ch15-abort /* Компилировать без -O */
$ ch15-abort /* Запустить программу */
Aborted (core dumped) /* Она печально завершается */
$ gdb ch15-abort core.4124 /* Запустить для нее GDB */
GNU gdb 5.3
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU
General Public License, and you are
welcome to change it and/or distribute copies of it
under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Core was generated by 'ch15-abort'.
Program terminated with signal 6, Aborted.
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x42028ccl in kill() from /lib/i686/libc.so.6
(gdb) where /* Вывести трассировку стека */
#0 0x42028cc1 in kill() from /lib/i686/libc.so.6
#1 0x42028ac8 in raise() from /lib/i686/libc.so.6
#2 0x4202a019 in abort() from /lib/1686/libc.so.6
#3 0x08048342 in recurse() at ch15-abort.c:13
 /* <-- Нам нужно исследовать здесь */
#4 0x08048347 in recurse() at ch15-abort.с:15
#5 0x08048347 in recurse() at ch15-abort.c:15
#6 0x0804835f in main (argc=1, argv=0xbffff8f4) at ch15-abort.c:20
#7 0x420158d4 in __libc_start_main() from /lib/i686/libc.so.6

Команда where выводит трассировку стека, то есть список всех вызванных функций, начиная с самых недавних. Обратите внимание, что имеется три вызова функции recurse(). Команда bt, означающая 'back trace' (обратная трассировка), является другим названием для where; ее легче набирать.

Вызов каждой функции в стеке называется фреймом. Этот термин пришел из области компиляторов, в которой параметры, локальные переменные и адреса возврата каждой функции, сгруппированные в стеке, называются фреймом стека. Команда frame GDB дает вам возможность исследовать определенный фрейм. В данном случае нам нужен фрейм 3. Это последний вызов recurse(), который вызвал abort():

(gdb) frame 3 /* Переместиться в фрейм 3 */
#3 0x08048342 in recurse() at ch15-abort.с:13
13 abort(); /* GDB выводит в фрейме положение в исходном коде */
(gdb) list /* Показать несколько строк исходного кода */
8  void recurse(void)
9  {
10  static int i;
11
12  if (++i == 3)
13   abort();
14  else
15   recurse();
16 }
17
(gdb) /* Нажатие ENTER повторяет последнюю команду */
18 int main(int argc, char **argv)
19 {
20  recurse();
21 }
(gdb) quit /* Выйти из отладчика (пока) */

Как показано, нажатие ENTER повторяет последнюю команду, в данном случае list, для отображения строк исходного кода. Это простой способ прохождения исходного кода.

Для редактирования командной строки GDB использует библиотеку readline, поэтому для повторения и редактирования ранее введенных команд можно использовать команды Emacs или vi. Оболочка Bash использует ту же самую библиотеку, поэтому если вам более знакомо редактирование командной строки в приглашении оболочки, GDB работает таким же образом. Эта особенность дает возможность избежать утомительного ручного ввода.

Оглавление книги


Генерация: 1.205. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз