Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Программирование и алгоритмические языки в Linux

Удаленная отладка с помощью GDB и GDBserver

Оригинал: Remote cross-target debugging with GDB and GDBserver
Автор: Avi Rozen
Дата: 28 ноября 2007
Перевод: Александр Тарасов aka oioki
Дата перевода: 3 января 2008

При копировании материала обязательны указание автора, переводчика и ссылки на оригинал статьи и настоящую страницу как первоисточник перевода!

Теоретически GDB (GNU debugger) может облегчить рутинную отладку приложений на встроенных Linux-системах. На практике же установка GDB для этой цели - своеобразный вызов разработчику; требуется преодолеть некоторые трудности технического характера. Тем не менее, польза очевидна: гораздо удобнее и правильней отлаживать программу, чем слепо гадать, в каком месте происходит ошибка. Ниже приведены советы, которые помогут разрешить имеющиеся трудности.

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

Обычно процессор на рабочей станции разработчика (к примеру, процессор класса i686) отличается от процессора на целевой платформе (ARM, PowerPC или что-нибудь еще). Это означает, что нельзя просто так взять исполняемый файл GDB с рабочей станции и скопировать его на целевую машину. Нет, требуется кросс-целевой отладчик. Иными словами, потребуется собрать GDB из исходных кодов.

Сборка GDB

В приведенном примере целевым процессором является 7450 PowerPC.

Прежде чем начать, требуется линия связи между PC с запущенным GDB и целевой платформой: это может быть последовательный порт или, что лучше, Ethernet-кабель. Также потребуется кросс-целевой набор программ для компиляции (cross-target toolchain): компилятор GNU C (с runtime-библиотекой C и бинарными утилитами binutils), который бы работал на рабочей станции разработчика и генерировал исполняемые файлы для целевого процессора. Придется собрать два набора бинарных файлов из исходников GDB:

  • cross-target - здесь под host будем понимать рабочую станцию, под target - целевой процессор
  • native - как host, так и target - целевой процессор

Сначала скачаем исходный код GDB в сжатом архиве и распакуем его:

Пакет исходных кодов GDB предназначен для сборки с помощью набора программ GNU. Обычно это означает, что пользователю придется отдать три стандартные команды (./configure ; make ; make install). Но в нашем случае сборка будет немного сложнее: нам нужно собрать бинарные файлы для двух различных процессоров и установить их в разные места. Поэтому будем собирать бинарники в их собственные каталоги, а не в каталог с исходными текстами. Для этого придется указать скрипту configure префикс установочного каталога, а также процессоры для host и target.

Для сборки кросс-целевых бинарных файлов нужно указать целевую архитектуру с помощью ключа --target. Идентификатор архитектуры (в данном случае powerpc-7450-linux-gnu) является префиксом для всех программ кроссовой компиляции (к примеру, компилятор C называется powerpc-7450-linux-gnu-gcc).

Собрать бинарные файлы для целевой платформы будет сложнее. Во-первых, нужно указать архитектуру для host (остается той же - powerpc-7450-linux-gnu). Во-вторых, отсутствие необходимых библиотек - некоторых библиотек может не быть в кроссовом наборе программ, и поэтому они должны быть скомпилированы перед сборкой GDB для целевой платформы. Ниже приведен пример того, как нужно действовать при отсутствии библиотеки termcap. Не забывайте в своих поисках использовать справку скрипта конфигурирования: ./configure --help.

Осталось рассмотреть один вопрос - должны ли бинарные файлы связываться статически? Ответ будет положительный, если на целевой платформе отсутствуют разделяемые библиотеки, от которых зависит работа GDB и GDBserver. Но в то же время статически связанные бинарные файлы больше в размере. Статическое связывание указывается с помощью ключа -static в переменной окружения LDFLAGS. Еще в этой переменной, а также в переменной CPPFLAGS, должны быть указаны любые другие дополнительные библиотеки, например:

Редактор связей GNU может выкинуть несколько предупреждений в ходе компиляции. Если статически связанное приложение использует некоторые функции (к примеру, dlopen, gethostbyname и другие), то для его запуска потребуются разделяемые библиотеки GNU C runtime той же версии, что использовалась при связывании. Возможно, придется доустанавливать эти библиотеки на целевую платформу.

После сборки исполняемого файла GDBserver нужно скопировать его на целевую платформу. Можно сохранить немного места на диске, удалив отладочную информацию из программы с помощью powerpc-7450-linux-gnu-strip gdbserver.

Сборка для другой целевой платформы должна свестись лишь к замене идентификатора архитектуры на нужный.

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

Для проведения отладки нужно скомпилировать приложение с отладочной информацией, дописав ключ -g при вызове компилятора или редактора связей. Получившейся исполняемый файл может быть достаточно велик и может не поместиться на целевой платформе. Тогда поступим почти как и с gdbserver - удалим отладочную информацию с помощью powerpc-7450-linux-gnu-strip. Но! Для дальнейших нужд требуется оставить копию, содержащую отладочную информацию. Итак, файл без отладочной информации копируем на целевую платформу, он предназначен для запуска с GDBserver на целевой платформе, а файл с отладочной информацией будет загружен в отладчик GDB на рабочей станции.

Удаленная отладка на самом деле прямолинейна: на целевой платформе нужно запустить GDBserver, указав хост и порт для прослушивания входящих TCP-соединений:

На рабочей станции разработчика нужно запустить кросс-целевой GDB:

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

После выполнения этих команд GDB подсоединится к GDBserver, работающему на целевой платформе, будет установлена точка останова на входе в главную функцию main и программе будет дозволено дойти до этой точки.

Также можно подсоединить GDBserver к уже работающему процессу:

Процесс будет приостановлен, и можно будет запустить удаленный отладчик GDB.

Исполнение команд GDB, как и предполагалось, не отличается от их выполнения на локальной машине, за редким исключением - например, команда run не используется, ведь программа уже запущена при запуске удаленной отладочной сессии. Еще одна особенность - при завершении программы удаленный GDBserver также завершается и удаленная отладочная сессия закрывается.

Установка работающего окружения удаленной отладки, несомненно, нетривиальна. Кто-то скажет, что "нет ничего лучше хорошо размещенного printf" (в целях отладки). Но так пройдет лишь в простейших случаях. Разумеется, с GDB вы держите в своих руках все аспекты работающей программы - код, данные, стек вызовов и т.п. Это не панацея, GDB не исправит магическим образом все ошибки в программе, но, несомненно, поможет вам в этом.