GNU Debugger ( GDB ) — это портативный отладчик , работающий на многих Unix-подобных системах и работающий со многими языками программирования , включая Ada , Assembly , C , C++ , D , Fortran , Haskell , Go , Objective-C , OpenCL C , Modula-2 , Pascal , Rust , [2] и частично другие. [3]
GDB был впервые написан Ричардом Столлманом в 1986 году как часть его системы GNU , после того как его GNU Emacs стал «достаточно стабильным». [4] GDB — это свободное программное обеспечение, выпущенное по лицензии GNU General Public License (GPL). Он был создан по образцу отладчика DBX , который поставлялся с дистрибутивами Berkeley Unix . [4]
С 1990 по 1993 год его поддерживал Джон Гилмор . [5] Сейчас его поддерживает Руководящий комитет GDB, который назначается Фондом свободного программного обеспечения . [6]
GDB предлагает обширные возможности для отслеживания и изменения выполнения компьютерных программ . Пользователь может отслеживать и изменять значения внутренних переменных программ и даже вызывать функции независимо от обычного поведения программы.
Целевые процессоры GDB (по состоянию на 2003 год) включают: Alpha , ARM , AVR , H8/300 , Altera Nios / Nios II , System/370 , System 390 , X86 и его 64-разрядное расширение X86-64 , IA-64 «Itanium», Motorola 68000 , MIPS , PA-RISC , PowerPC , SuperH , SPARC и VAX . Менее известные целевые процессоры, поддерживаемые в стандартной версии, включают A29K , ARC , ETRAX CRIS , D10V, D30V, FR-30, FR-V , Intel i960 , 68HC11 , Motorola 88000 , MCORE , MN10200, MN10300 , NS32K , Stormy16 и Z8000 . (Более новые версии, вероятно, не будут поддерживать некоторые из них.) GDB скомпилировал симуляторы даже для менее известных целевых процессоров, таких как M32R или V850 . [7]
GDB все еще активно разрабатывается. Начиная с версии 7.0 новые функции включают поддержку скриптов Python [8] , а с версии 7.8 — также скриптов GNU Guile . [9] Начиная с версии 7.0 доступна поддержка «обратимой отладки» — позволяющей сеансу отладки вернуться назад, что очень похоже на перемотку рухнувшей программы, чтобы увидеть, что произошло. [10]
GDB предлагает «удалённый» режим, часто используемый при отладке встраиваемых систем. Удалённая работа — это когда GDB работает на одной машине, а отлаживаемая программа — на другой. GDB может связываться с удалённой «заглушкой», которая понимает протокол GDB, через последовательное устройство или TCP/IP. [11] Программу-заглушку можно создать, связавшись с соответствующими файлами-заглушками, поставляемыми с GDB, которые реализуют целевую сторону протокола связи. [12] В качестве альтернативы gdbserver можно использовать для удалённой отладки программы без необходимости вносить в неё какие-либо изменения.
Тот же режим используется KGDB для отладки работающего ядра Linux на уровне исходного кода с помощью gdb. С помощью KGDB разработчики ядра могут отлаживать ядро почти так же, как они отлаживают прикладные программы. Это позволяет размещать точки останова в коде ядра, пошагово проходить по коду и наблюдать за переменными. На архитектурах, где доступны регистры аппаратной отладки, можно устанавливать точки наблюдения, которые запускают точки останова при выполнении или доступе к указанным адресам памяти. Для KGDB требуется дополнительная машина, которая подключается к машине для отладки с помощью последовательного кабеля или Ethernet . На FreeBSD также возможна отладка с использованием прямого доступа к памяти (DMA) FireWire . [13]
Отладчик не содержит собственного графического пользовательского интерфейса и по умолчанию использует интерфейс командной строки , хотя он содержит текстовый пользовательский интерфейс . Для него было создано несколько интерфейсов, таких как UltraGDB, Xxgdb, Data Display Debugger (DDD), Nemiver , KDbg, отладчик Xcode , GDBtk/Insight, Gede [1], Seer [2] и HP Wildebeest Debugger GUI (WDB GUI). Такие IDE , как Codelite , Code::Blocks , Dev-C++ , Geany , GNAT Programming Studio (GPS), KDevelop , Qt Creator , Lazarus , MonoDevelop , Eclipse , NetBeans и Visual Studio, могут взаимодействовать с GDB. GNU Emacs имеет «режим GUD» и существуют инструменты для Vim (например, clewn). Они предлагают возможности, похожие на отладчики, имеющиеся в IDE.
Для работы с GDB были разработаны и другие инструменты отладки, такие как детекторы утечек памяти .
GDB использует системный вызов ptrace (название является сокращением от «process trace») для наблюдения и управления выполнением другого процесса, а также для проверки и изменения памяти и регистров процесса.
Точка останова реализуется путем замены инструкции по указанному адресу памяти другой специальной инструкцией. Выполнение инструкции точки останова вызывает SIGTRAP.
Рассмотрим следующий исходный код, написанный на языке C :
#include <stdio.h> #include <stdlib.h> #include <string.h> size_t foo_len ( const char * s ) { return strlen ( s ); } int main ( int argc , char * argv [] ) { const char * a = NULL ; printf ( "размер a = %lu \n " , foo_len ( a ) ); выход ( 0 ); }
Используя компилятор GCC в Linux , код выше должен быть скомпилирован с использованием -g
флага, чтобы включить соответствующую отладочную информацию в сгенерированный двоичный файл, что позволит проверить его с помощью GDB. Предполагая, что файл, содержащий код выше, называется example.c
, команда для компиляции может быть следующей:
$ gcc пример.c -Og -g -o пример
И теперь двоичный файл можно запустить:
$ ./example Ошибка сегментации
Поскольку при выполнении примера кода генерируется ошибка сегментации , для изучения проблемы можно использовать GDB.
$ gdb ./example GNU gdb (GDB) Fedora (7.3.50.20110722-13.fc16) Авторские права (C) 2011 Free Software Foundation, Inc. Лицензия GPLv3+: GNU GPL версии 3 или более поздней <https://gnu.org/licenses/gpl.html> Это свободное программное обеспечение: вы можете изменять и распространять его. НЕТ НИКАКИХ ГАРАНТИЙ, в той мере, в какой это разрешено законом. Введите "show copying" и "show warranty" для получения подробной информации. Этот GDB был настроен как "x86_64-redhat-linux-gnu". Инструкции по отправке сообщений об ошибках см. на странице <https://www.gnu.org/software/gdb/bugs/>... Чтение символов из /path/example...выполнено. (gdb) запустить Запуск программы: /path/exampleПрограмма получила сигнал SIGSEGV, Ошибка сегментации. 0x0000000000400527 в foo_len (s=0x0) в example.c:7 7 return strlen (s); (gdb) print s $ 1 = 0x0
Проблема присутствует в строке 7 и возникает при вызове функции strlen
(потому что ее аргумент, s
, равен NULL
). В зависимости от реализации strlen ( встроенной или нет), вывод может быть разным, например:
GNU gdb (GDB) 7.3.1 Авторские права (C) 2011 Free Software Foundation, Inc. Лицензия GPLv3+: GNU GPL версии 3 или более поздней <https://gnu.org/licenses/gpl.html> Это свободное программное обеспечение: вы можете изменять и распространять его. ГАРАНТИИ НЕТ, в той мере, в какой это разрешено законом. Введите "show copying" и "show warranty" для получения подробной информации. Этот GDB был настроен как "i686-pc-linux-gnu". Инструкции по отправке сообщений об ошибках см. на странице <https://www.gnu.org/software/gdb/bugs/>... Чтение символов из /tmp/gdb/example...выполнено. (gdb) запустить Запуск программы: /tmp/gdb/exampleПрограмма получила сигнал SIGSEGV, Ошибка сегментации. 0xb7ee94f3 в strlen() из /lib/i686/cmov/libc.so.6 (gdb) bt # 0 0xb7ee94f3 в strlen () из /lib/i686/cmov/libc.so.6 # 1 0x08048435 в foo_len ( s = 0x0 ) в example.c:7 # 2 0x0804845a в main ( argc = <optimized out>, argv = <optimized out> ) в example.c:14
Чтобы исправить проблему, переменная a
(в функции main
) должна содержать допустимую строку. Вот исправленная версия кода:
#include <stdio.h> #include <stdlib.h> #include <string.h> size_t foo_len ( const char * s ) { return strlen ( s ); } int main ( int argc , char * argv [] ) { const char * a = "Это тестовая строка" ; printf ( "размер a = %lu \n " , foo_len ( a ) ); выход ( 0 ); }
Повторная компиляция и запуск исполняемого файла внутри GDB теперь дает правильный результат:
$ gdb ./example GNU gdb (GDB) Fedora (7.3.50.20110722-13.fc16) Авторские права (C) 2011 Free Software Foundation, Inc. Лицензия GPLv3+: GNU GPL версии 3 или более поздней <https://gnu.org/licenses/gpl.html> Это свободное программное обеспечение: вы можете изменять и распространять его. НЕТ НИКАКИХ ГАРАНТИЙ, в той мере, в какой это разрешено законом. Введите "show copying" и "show warranty" для получения подробной информации. Этот GDB был настроен как "x86_64-redhat-linux-gnu". Инструкции по отправке сообщений об ошибках см. на странице <https://www.gnu.org/software/gdb/bugs/>... Чтение символов из /path/example...выполнено. (gdb) запустить Запуск программы: /path/example размер a = 21 [Подчиненный процесс 1 (процесс 14290) завершился нормально]
GDB выводит вывод printf
на экран, а затем информирует пользователя о том, что программа завершилась нормально.
Затем, после того как GNU Emacs стал достаточно стабильным, что заняло в общей сложности около полутора лет, я начал возвращаться к другим частям системы. Я разработал отладчик, который назвал GDB, который является символическим отладчиком для кода C, который недавно поступил в дистрибуцию. Теперь этот отладчик в большой степени в духе DBX, который является отладчиком, поставляемым с Berkeley Unix.