GDB — это консольное приложение, выполненное в классическом духе командной строки. Вот краткое руководство по использованию отладчика GDB.
Еще по теме: Обход защиты StarForce
И хотя за время своего существования GDB успел обрасти ворохом красивых графических морд (среди них DDD, Data Display Debugger, — старейший и самый популярный интерфейс), интерактивная отладка в стиле WinDBG в мире Linux крайне непопулярна.
Как правило, это удел эмигрантов с Windows-платформы, сознание которых необратимо искалечено идеологией «окошек». Грубо говоря, если WinDBG — слесарный инструмент, то GDB — токарный станок с программным управлением. Когда‑нибудь вы полюбите его.
Для отладки на уровне исходных текстов программа должна быть откомпилирована с отладочной информацией. В GCC за это отвечает ключ -g. Если отладочная информация недоступна, GDB будет отлаживать программу на уровне дизассемблерных команд.
Обычно имя отлаживаемого файла передается в командной строке:
1 |
gdb filename |
Для отладки активного процесса укажите в командной строке его ID, а для подключения коры (core dump) воспользуйтесь ключом:
1 |
—core==corename |
Все три параметра можно загружать одновременно, попеременно переключаясь между ними командой target.
Переключаемся на отлаживаемый файл:
1 |
target exec |
На приаттаченный процесс:
1 |
target child |
Или на дамп коры:
1 |
target core |
Необязательный ключ -q подавляет вывод копирайта. Загрузив программу в отладчик, мы должны установить точку останова. Для этого служит команда break (она же b).
1 |
b main |
Эта команда устанавливает точку останова на функцию main языка C, а вот эта:
1 |
b _start |
на точку входа в ELF-файл (впрочем, в некоторых файлах она называется по‑другому). Можно установить точку останова и на произвольный адрес:
1 |
b *0x8048424 |
или
1 |
b *$eax |
Регистры пишутся маленькими буквами и предваряются знаком доллара. GDB понимает два «общесистемных» регистра: $pc — указатель команд и $sp — стековый указатель. Только помните, что непосредственно после загрузки программы в отладчик никаких регистров у нее еще нет, они появляются только после запуска отлаживаемого процесса на выполнение (команда run, она же r).
Отладчик самостоятельно решает, какую точку останова установить, программную или аппаратную, и лучше ему не препятствовать (команда принудительной установки аппаратной точки останова hbreak работает не на всех версиях отладчика). Точки останова на данные в GDB называются точками наблюдения — watch point.
Перечислю основные приемы работы с отладчиком.
- watch addr вызывает отладчик всякий раз, когда содержимое addr изменяется, а awatch addr — при чтении или записи в addr.
- rwatch addr реагирует только на чтение, но работает не во всех версиях отладчика.
- info break позволяет просмотреть список установленных точек останова.
- clear удаляет все точки останова.
- clear addr удаляет все точки останова, установленные на данную функцию, адрес или номер строки.
- enable и disable позволяют временно включать и отключать точки останова. Точки останова поддерживают развитый синтаксис условных команд, описание которого можно найти в документации.
- continue ( c) возобновляет выполнение программы, прерванное точкой останова.
- next N ( n N) выполняет N следующих строк кода без входа, а step N ( s N) сo входом во вложенные функции. Если число N не задано, по умолчанию выполняется одна строка.
- nexti и stepi делают то же самое, но работают не со строками исходного текста, а с машинными командами. Обычно они используются совместно с командой display/i $pc (x/i $pc), предписывающей отладчику отображать текущую машинную команду. Ее достаточно вызывать один раз за сеанс.
- jump addr передает управление в произвольную точку программы, а call addr/fname вызывает функцию fname с аргументами! Этого нет даже во многих Windows-отладчиках. А как часто оно требуется!
- Другие полезные команды:
- finish — продолжать выполнение до выхода из текущей функции;
- until addr ( u addr) — продолжать выполнение, пока указанное место не будет достигнуто, при запуске без аргументов — остановить выполнение при достижении следующей команды (актуально для циклов!);
- return — немедленно вернуться в дочернюю функцию.
- Команда
print (
p) выводит значение:
- выражения (например, p 1+2);
- содержимого переменной ( p my_var);
- содержимого регистра ( p $eax);
- ячейки памяти ( p *0x8048424, p *$eax).
- Если необходимо вывести несколько ячеек, воспользуйтесь командой x/Nh addr, где N — количество выводимых ячеек. Ставить символ звездочки перед адресом в этом случае не нужно.
- info registers ( i r) выводит значение всех доступных регистров.
- Модифицирует содержимое ячеек памяти/регистров команда
set:
- set $eax = 0 записывает в регистр eax ноль;
- set var my_var = $ecx присваивает переменной my_var значение регистра ecx;
- set {unsigned char*}0x8048424=0xCC записывает по байтовому адресу 0x8048424 число 0xCC.
- disassemble _addr_from _addr_to выдает содержимое памяти в виде дизассемблерного листинга, формат представления которого определяется командой set disassembly-flavor.
- info frame, info args, info local отображают содержимое текущего фрейма стека, аргументы функции и локальные переменные. Для переключения на фрейм материнских функций служит команда frame N. Команда backtrace ( bt) делает то же самое, что и call stack в Windows-отладчиках. При исследовании дампов коры она незаменима.
Короче говоря, приблизительный сеанс работы с GDB выглядит так: грузим программу в отладчик, отдаем ему команду b main, а если не сработает, то b _start, затем r, после чего отлаживаем программу по шагам ( n/s), при желании задав параметры ( x/i $pc), чтобы GDB показывал, что у нас выполняется в данный момент.
Выходим из отладчика по команде quit ( q). Описание остальных команд ищите в документации. Теперь по крайней мере вы не заблудитесь в ней.
Еще есть графический интерфейс gdbgui, который запускается внутри браузера.
Он представляет собой серверное приложение, написанное на Python, и устанавливается через pip:
1 |
sudo pip install gdbgui --upgrade |
На выполнение он запускается подобно GDB:
1 |
gdbgui filename |
Сравнение Linux-отладчиков с Windows-отладчиками показывает значительное отставание последних и их непрофессиональную направленность. Трехмерные кнопки, масштабируемые иконки, всплывающие меню [kk9] — все это, конечно, очень красиво, но в GDB проще написать макрос или использовать уже готовый (благо все, что только было можно запрограммировать, здесь запрограммировали задолго до нас).
Между тем отладочные средства в Linux не замыкаются на одном только GDB. Однако GDB с течением времени доказывает свою исключительность. Как мы увидели, GDB покрывает все задачи отладки, и другого в Linux не надо.
Единственное, чего ему недостает, — нормальный ядерный отладчик системного уровня, ориентированный на работу с двоичными файлами без символьной информации и исходных тестов. Тяжелое детство и скитание по множеству платформ наложило на UNIX мрачный отпечаток в виде стремления к переносимости и кросс‑платформенности. Какое там хакерство в таких условиях! Впрочем, доступность исходных текстов делает эту проблему неактуальной.
ПОЛЕЗНЫЕ ССЫЛКИ:
- Отладка программ с помощью WinDbg
- Удаленная отладка вредоносных программ
- Отладка нативной библиотеки Android и iOS с помощью GDB