Отладка с помощью GDB - 13. Определение отладочной цели
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]13. Определение отладочной цели
Цель---это среда выполнения, занятая вашей программой.
Часто GDB выполняется в той же рабочей среде, что и ваша
программа; в этом случае, отладочная цель задается неявно в момент
использования команд file
или core
. Когда вам нужна
большая гибкость--например, выполнение GDB на другой машине, или
управление автономной системой через последовательный порт или системой
реального времени через соединение TCP/IP--вы можете использовать
команду target
для определения цели одного из типов,
сконфигурированных для GDB (см. раздел 13.2 Команды для управления целями).
13.1 Активные цели
Существует три класса целей: процессы, файлы дампов памяти и выполняемые файлы. GDB может обрабатывать одновременно до трех активных целей, по одной в каждом классе. Это позволяет вам (например) запустить процесс и проверять его действия, не прерывая вашу работу над файлом дампа.
Например, если вы выполняете `gdb a.out', то исполняемый файл
a.out
является единственной активной целью. Если вы назначите также
файл дампа--возможно от предыдущего выполнения, завершившегося ошибкой
и создавшего дамп---
тогда GDB имеет две активные цели и использует их вместе,
просматривая сначала файл дампа, а затем исполняемый файл, для выполнения
запросов к адресам памяти. (Обычно эти два класса целей дополняют друг
друга, так как файлы дампа памяти содержит только память программы,
доступную для чтения и записи
(переменные и тому подобное), и машинное состояние, в то время как исполняемый
файлы содержат только текст программы и инициализированные данные.)
Когда вы вводите run
, ваш исполняемый файл становится также активным
целевым процессом. Когда целевой процесс активен, все команды GDB,
запрашивающие адреса памяти, относятся к этой цели; адреса в активной
цели файла дампа или выполняемого файла неизвестны, пока активен
целевой процесс.
Используйте команды core-file
и exec-file
для выбора новой
цели файла дампа памяти или выполняемого файла (см. раздел 12.1 Команды для задания файлов). Для определения в качестве цели
процесса, который уже выполняется, используйте команду attach
(см. раздел 4.7 Отладка запущенного ранее процесса).
13.2 Команды для управления целями
target тип параметры
-
Соединяет рабочую среду GDB с целевой машиной или процессом.
Целью обычно является протокол для взаимодействия со средствами отладки.
Параметр тип используется, чтобы определить тип или протокол
целевой машины.
Дальнейшие параметры интерпретируются целевым
протоколом, но обычно включают такие вещи, как имена
устройств или имена рабочих машин, с которыми осуществляется
связь, номера процессов и скорости в бодах.
Команда
target
не повторяется при повторном нажатии RET после ее выполнения. help target
-
Отображает имена всех доступных целей. Чтобы отобразить выбранные в
данный момент цели, используйте либо
info target
, либоinfo files
(см. раздел 12.1 Команды для задания файлов). help target имя
- Описывает определенную цель, включая любые параметры, необходимые для ее выбора.
set gnutarget арг
-
GDB использует свою собственную библиотеку BFD(14) для чтения ваших
файлов. GDB знает, читает ли он выполняемый файл,
файл дампа памяти или объектный (.o) файл; однако вы можете
определить формат файла командой
set gnutarget
. В отличие от большинства командtarget
, сgnutarget
, командаtarget
относится к программе, а не к машине.Предупреждение: Для определения формата файла посредством
set gnutarget
, вы должны знать фактическое имя BFD. show gnutarget
-
Используйте команду
show gnutarget
для отображения, какого формата файлыgnutarget
установлен считывать. Если вы не установилиgnutarget
, GDB определит формат для каждого файла автоматически, иshow gnutarget
выведет `The current BFD target is "auto"'.
Ниже приведены некоторые наиболее распространенные цели (доступные или нет, в зависимоси от конфигурации GDB):
target exec программа
- Выполняемый файл. `target exec программа' то же самое, что и `exec-file программа'.
target core имя-файла
- Файл дампа памяти. `target core имя-файла' то же самое, что и `core-file имя-файла'.
target remote устр
-
Удаленная последовательная цель является уникальным для GDB
протоколом. Параметр устр определяет, какое последовательное
устройство использовать для соединения (например, `/dev/ttya').
См. раздел 13.4 Удаленная отладка.
target remote
поддерживает командуload
. Это полезно, только если вы можете получить заглушку для целевой системы каким-нибудь другим способом и можете разместить ее в памяти, где она не будет затерта загрузкой. target sim
-
Встроенный эмулятор ЦП. GDB включает эмуляторы для большинства
архитектур. Вообще,
target sim load run
работает; однако, вы не можете предположить, что доступны определенное отображение памяти, драйверы устройств, или даже основные функции ввода-вывода, хотя некоторые эмуляторы действительно предоставляют это. Для информации о деталях эмуляторов для конкретного процессора, смотрите соответствующий раздел 14.3 Встроенные процессоры.
Некоторые конфигурации могут также включать такие цели:
Для различных конфигураций GDB доступны различные цели; ваша конфигурация может иметь больше или меньше целей.
Многие удаленные цели требуют, чтобы вы загрузили код выполняемого файла, после того как вы успешно установили соединение.
load имя-файла
-
В зависимости от того, какие возможности удаленной отладки
сконфигурированы в GDB, может быть доступна команда
load
. Если она существует, ее задачей является сделать имя-файла (выполняемый файл) доступным для отладки на удаленной системе--например, путем загрузки или динамической сборки.load
также записывает таблицу символов имя-файла в GDB, как командаadd-symbol-file
. Если ваш GDB не имеет командыload
, попытка выполнить ее выдает сообщение об ошибке "You can't do that when your target is ...
". Файл загружается по адресу, указанному в выполняемом файле. Для некоторых форматов объектных файлов, вы можете задать адрес загрузки при сборке программы; для других форматов, таких как a.out, формат объектного файла задает фиксированный адрес.load
не повторяется, если вы нажимаете RET снова после ее использования.
13.3 Выбор целевого порядка байтов
Некоторые типы процессоров, такие как MIPS, PowerPC и Hitachi SH, предоставляют возможность выполнения либо с порядком байтов от старшего, либо с порядком байтов от младшего. Обычно, выполняемый файл или символы содержат информацию для определения используемого порядка байтов, и вам не нужно об этом заботиться. Однако, иногда вам все же может пригодиться вручную изменить порядок байтов процессора, определенный GDB.
set endian big
- Велит GDB считать, что целевой порядок байтов от старшего.
set endian little
- Велит GDB считать, что целевой порядок байтов от младшего.
set endian auto
- Велит GDB использовать порядок байтов, указанный в выполняемом файле.
show endian
- Отображает текущую установку GDB для целевого порядка байтов.
Заметьте, что эти команды управляют только интерпретацией символьных данных в рабочей системе, и они совершенно не оказывают действия на целевую систему.
13.4 Удаленная отладка
Если вы пытаетесь отлаживать программу, выполняющуюся на машине, которая не может запустить GDB обычным способом, часто бывает полезна удаленная отладка. Например, вы можете использовать удаленную отладку для ядра операционной системы или для малой системы, которая не имеет достаточно мощной операционной системы общего назначения для вызова отладчика со всеми возможностями.
Некоторые конфигурации GDB имеют специальный последовательный или TCP/IP интерфейсы для того, чтобы это работало с конкретными отладочными целями. Кроме того, GDB распространяется с общим последовательным протоколом (уникальным для GDB, но не для конкретной целевой системы), который вы можете использовать, если пишете удаленные заглушки--код, выполняемый в удаленной системе для связи с GDB.
В вашей конфигурации GDB могут быть доступны другие удаленные
цели; используете help target
, чтобы их перечислить.
13.4.1 Удаленный последовательный протокол GDB
Для отладки программы, выполняемой на другой машине (отладочной целевой машине), вы сперва должны создать все обычные предпосылки для самостоятельного выполнения программы. Например, для программы на Си вам нужны:
- Процедура запуска для установки среды выполнения Си; она обычно имеет имя типа `crt0'. Процедура запуска может быть обеспечена вашими аппаратными средствами, или вы должны написать свою собственную.
- Библиотека подпрограмм Си для поддержки вызовов подпрограмм вашей программы, особенно для управления вводом и выводом.
- Способ установки вашей программы на другую машину--например, программа загрузки. Такие программы часто предоставляются поставщиками аппаратных средств, но вам может потребоваться написать вашу собственную, пользуясь документацией к аппаратному обеспечению.
Следующим шагом будет принятие мер по использованию вашей программой последовательного порта для связи с машиной, где выполняется GDB (рабочей машиной). В общих чертах, схема выглядит следующим образом:
- На рабочей машине
- GDB уже понимает, как использовать этот протокол; после установки всего остального, вы можете просто использовать команду `target remote' (см. раздел 13. Определение отладочной цели).
- На целевой машине
-
вы должны скомпоновать вместе с вашей программой несколько подпрограмм
специального назначения, которые реализуют удаленный последовательный
протокол GDB. Файл, содержащий эти подпрограммы, называется
отладочной заглушкой.
На некоторых удаленных целях, вы можете использовать вспомогательную
программу
gdbserver
вместо компоновки заглушки вместе с вашей программой. См. раздел 13.4.1.5 Использование программыgdbserver
, для детального изучения.
Отладочная заглушка специфична для архитектуры удаленной машины; например, используйте `sparc-stub.c' для отладки программ на машинах SPARC.
Следующие работающие удаленные заглушки распространяются вместе с GDB:
i386-stub.c
- Для Intel 386 и совместимых архитектур.
m68k-stub.c
- Для архитектур Motorola 680x0.
sh-stub.c
- Для архитектур Hitachi SH.
sparc-stub.c
- Для архитектур SPARC.
sparcl-stub.c
- Для архитектур Fujitsu SPACRLITE.
Файл `README' в поставке GDB может содержать другие недавно добавленные заглушки.
13.4.1.1 Что заглушка может сделать для вас
Отладочная заглушка для вашей архитектуры содержит следующие три подпрограммы:
set_debug_traps
-
Когда ваша программа останавливается, эта подпрограмма организует
выполнение
handle_exception
. Вы должны явно вызвать эту подпрограмму в начале вашей программы. handle_exception
-
Это главная рабочая лошадка, но ваша программа никогда не вызывает ее
явно--установочный код организует запуск
handle_exception
, когда вызывается ловушка.handle_exception
получает управление, когда ваша программа останавливается во время выполнения (например, в точке останова), и организует связь с GDB на рабочей машине. Именно здесь реализуется протокол связи;handle_exception
действует как представитель GDB на целевой машине. Сперва она посылает суммарную информацию о состоянии вашей программы, затем продолжает выполняться, извлекая и передавая любую информацию, требующуюся GDB, пока вы не выполните команду GDB, возобновляющую выполнение вашей программы; в этом местеhandle_exception
возвращает управление вашему коду на целевой машине. breakpoint
-
Используйте эту вспомогательную подпрограмму для установки в вашей
программе точек останова. В зависимости от конкретной ситуации, это
может быть единственным способом для GDB получить управление.
Например, если ваша целевая машина имеет некую клавишу прерывания, вам
не нужно вызывать эту подпрограмму; нажатие клавиши прерывания передаст
управление
handle_exception
---в действительности, GDB. На некоторых машинах простое получение символов на последовательный порт может также вызвать ловушку; опять, в этой ситуации вам не нужно вызыватьbreakpoint
из вашей программы--простое выполнение `target remote' из рабочего сеанса GDB передаст управление. Вызывайтеbreakpoint
, если ни одно из этих предположений не верно, или вы просто хотите быть уверенным, что ваша программа остановится в предопределенной точке от начала вашего сеанса отладки.
13.4.1.2 Что вы должны сделать для заглушки
Отладочные заглушки, поставляемые с GDB, ориентированы на микропроцессоры определенной архитектуры, но они не имеют информации об остальной части вашей целевой отладочной машины.
В первую очередь, вам нужно сообщить заглушке, как связаться с последовательным портом.
int getDebugChar()
-
Напишите эту подпрограмму для чтения одного символа из
последовательного порта. Она может быть идентична
getchar
для вашей целевой системы; разные имена используются, чтобы позволить вам их различать, если вы этого хотите. void putDebugChar(int)
-
Напишите эту подпрограмму для записи одного символа в
последовательный порт. Она может быть идентична
putchar
для вашей целевой системы; разные имена используются, чтобы позволить вам их различать, если вы этого хотите.
Если вы хотите, чтобы GDB мог остановить вашу программу во
время ее выполнения, вам нужно использовать управляемый прерываниями
последовательный драйвер и настроить его для остановки при получении
^C
(`\003', символ control-C). Это тот символ, который
GDB использует для указания удаленной системе остановиться.
Указание отладочной цели вернуть GDB правильный статус,
вероятно, требует изменений стандартной заглушки; один быстрый и
неаккуратный способ состоит в выполнении лишь инструкции точки останова
("неаккуратность" состоит в том, что GDB выдает
SIGTRAP
вместо SIGINT
).
Вот другие процедуры, которые вы должны обеспечить:
void exceptionHandler (int номер-исключения, void *адрес-исключения)
-
Напишите эту функцию для установки адреса-исключения в таблицы
обработки исключительных ситуаций. Вам нужно сделать это, потому
что у заглушки нет способа узнать, как устроены таблицы обработки
исключений в вашей целевой системе (например, процессорная
таблица может быть в ПЗУ, и содержать элементы, указывающие на
таблицу в ОЗУ). Номер-исключения---это номер исключительной
ситуации, которая должна быть изменена; его значение зависит от
архитектуры (например, различные номера могут представлять
деление на ноль, доступ с нарушением выравнивания, и так далее). Когда
это исключение возникает, управление должно быть передано
непосредственно адресу-исключения, и процессорное
состояние (стек, регистры и так далее) должно быть таким же, как
во время возникновения процессорного исключения. Так что если вы хотите
использовать инструкцию перехода для достижения адреса-исключения,
это должен быть простой переход, не переход к подпрограмме.
Для 386, адрес-исключения должен быть установлен как обработчик
затвора вызова
прерывания, чтобы во время его выполнения остальные прерывания маскировались.
Он должен иметь уровень полномочий 0 (наибольшие полномочия). Заглушки
SPARC и 68k могут маскировать прерывания самостоятельно без помощи
exceptionHandler
. void flush_i_cache()
- Только для SPARC и SPARCLITE. Напишите эту попрограмму для очистки кеша инструкций, если он есть, на вашей целевой машине. Если кеша инструкций нет, эта подпрограмма может ничего не делать. На целевых машинах, имеющих кеш инструкций, GDB требует эту функцию, чтобы удостовериться, что состояние вашей программы стабильное.
Вы должны также удостовериться, что эта библиотечная процедура доступна:
void *memset(void *, int, int)
-
Это стандартная библиотечная функция
memset
, которая устанавливает область памяти в заданное значение. Если вы имеете одну из свободных версийlibc.a
,memset
может быть найдена там; иначе вы должны или получить ее от изготовителя аппаратного обеспечения, или написать свою собственную.
Если вы не используете компилятор GNU Си, вам также могут
понадобиться другие стандартные библиотечные подпрограммы; это
меняется от одной заглушки к другой, но в общем, заглушки
часто используют различные общие библиотечные подпрограммы, которые
gcc
генерирует как встроенный код.
13.4.1.3 Собираем все вместе
Вкратце, когда ваша программа готова к отладке, вы должны проделать следующие шаги.
-
Убедитесь, что вы определили поддерживающие процедуры низкого уровня
(см. раздел 13.4.1.2 Что вы должны сделать для заглушки):
getDebugChar
,putDebugChar
,flush_i_cache
,memset
,exceptionHandler
. -
Вставьте следующие строки в начале вашей программы:
set_debug_traps(); breakpoint();
-
Для заглушки 680x0, вы должны предоставить переменную
exceptionHook
. Обычно вы используете просто:void (*exceptionHook)() = 0;
если до вызоваset_debug_traps
вы установили ее для указания на функцию в вашей программе. Эта функция вызывается, когда GDB продолжает выполнение после останова на ловушке (например, ошибка шины). Функция, указаннаяexceptionHook
, вызывается с одним параметром типаint
, который является номером исключения. - Откомпилируйте и скомпонуйте вместе: вашу программу, отладочную заглушку GDB для вашей целевой архитектуры и подпрограммы поддержки.
- Убедитесь, что у вас есть последовательное соединение между вашей целевой и рабочей машинами, и идентифицируйте последовательный порт на рабочей машине.
- Загрузите вашу программу на целевую машину (или поместите ее туда любыми средствами, предоставляемыми производителем) и запустите ее.
- Для начала удаленной отладки, запустите GDB на рабочей машине и укажите в качестве выполняемого файла программу, которая выполняется на удаленной машине. Это сообщает GDB, как найти символы и содержание неизменяемых областей вашей программы.
-
Установите связь, используя команду
target remote
. Ее аргументы определяют, как взаимодействовать с целевой машиной--- либо через устройство, подключенное к последовательной линии, либо через порт TCP (обычно подключенный к терминальному серверу, который, в свою очередь, имеет последовательную линию до цели). Например, чтобы использовать последовательную линию, присоединенную к устройству `/dev/ttyb', выполните:target remote /dev/ttyb
Чтобы использовать TCP-соединение, используйте аргумент в формемашина:порт
. Например, для соединения с портом 2828 на терминальном сервереmanyfarms
:target remote manyfarms:2828
Теперь вы можете использовать все обычные команды для исследования и изменения данных, пошагового выполнения и продолжения исполнения удаленной программы.
Для возобновления выполнения удаленной программы и прекращения ее
отладки, используйте команду detach
.
Всякий раз, когда GDB ожидает удаленную программу, если вы вводите символ прерывания (часто C-C), GDB пытается остановить программу. Это может привести или не привести к успеху, частично в зависимости от аппаратных средств и последовательных драйверов, которые использует удаленная система. Если вы снова введете символ прерывания, GDB выведет такое приглашение:
Interrupted while waiting for the program. Give up (and stop debugging it)? (y or n)
Если вы введете y, GDB прекратит сеанс удаленной отладки.
(Если вы решите позже, что хотите попытаться снова, вы можете вновь
использовать target remote
, чтобы соединиться еще раз.) Если вы
введете n, GDB вернется к ожиданию.
13.4.1.4 Коммуникационный протокол
Файлы заглушек, поставляемые с GDB, реализуют коммуникационный протокол со стороны целевой машины, а со стороны GDB он реализуется в исходном файле GDB `remote.c'. Обычно вы можете просто позволить этим программам взаимодействовать, и не вдаваться в детали. (Если вы разрабатываете свой собственный файл заглушки, вы также можете игнорировать детали: начните с одного из существующих файлов заглушки. `sparc-stub.c' организован наилучшим образом, и потому его легче всего читать.)
Однако, бывают случаи, когда вам необходимо что-нибудь знать о протоколе--например, если существует только один последовательный порт на вашей целевой машине, вы можете захотеть, чтобы ваша программа делала что-нибудь особенное, если она распознает предназначенный для GDB пакет.
В следующих примерах, `<-' и `->' используются для обозначения переданных и полученных данных соответственно.
Все команды и ответы GDB (не подтверждения), посылаются в виде пакета. Пакет представлен символом `$', реальными данными-пакета завершающим символом `#', за которым следуют две цифры контрольной-суммы:
$
данные-пакета#
контрольная-сумма
Двухциферная контрольная-сумма вычисляется как сумма по модулю 256 всех символов между начальным `$' и конечным `#' (восьмибитная беззнаковая контрольная сумма).
Разработчикам следует учесть, что до GDB версии 5.0 спецификация протокола также включала необязательный двухциферный ид-последов:
$
ид-последов:
данные-пакета#
контрольная-сумма
Этот ид-последов добавлялся к подтверждению. GDB никогда не генерировал ид-последов. Заглушки, занимающиеся обработкой пакетов, добавленные в GDB начиная с версии 5.0, не должны принимать пакеты с ид-последов.
Когда или рабочая, или целевая машина получает пакет, первым ожидаемым ответом является подтверждение: или `+' (для указания, что пакет получен корректно), или `-' (чтобы запросить повторную передачу):
<-$
данные-пакета#
контрольная-сумма ->+
Рабочая машина (GDB) посылает команды, а целевая (отладочная заглушка, включенная в вашу программу) посылает ответ. В случае команд пошагового выполнения и продолжения, ответ посылается только тогда, когда операция закончена (цель снова остановлена).
Данные-пакета состоят из последовательности знаков, за исключением `#' и `$' (для дополнительных исключений, смотрите пакет `X').
Поля внутри пакета должны разделяться при помощи `,', `;' или `:'. Если не оговорено противное, все числа представлены в шестнадцатеричном виде без начальных нулей.
Разработчикам следует учесть, что до GDB версии 5.0, символ `:' не мог появляться третим символом в пакете (так как потенциально это могло привести к конфликту с ид-последов).
Ответ данные может быть закодированным с помощью кодирования
методом длины серий, чтобы
сохранить место. `*' означает, что следующий символ является
ASCII-кодом, который означает количество повторений символа,
предшествующего `*'. Кодировкой является n+29
, что дает печатный
знак для n >=3
(когда кодировка переменной длины дает
преимущества). Печатные знаки `$', `#', `+', `-',
или с номерами, большими 126, использоваться не должны.
Некоторые удаленные системы использовали другой механизм кодировки с переменной длиной, иногда называемый cisco-кодировкой. За `*' следуют две шестнадцатеричные цифры, обозначающие размер пакета.
Итак:
"0*
"
означает то же, что и "0000".
При ошибке, ответ, возвращаемый для некоторых пакетов, включает двухсимвольный номер ошибки. Этот номер определен смутно.
Для любой команды, не поддерживаемой заглушкой, должен быть возвращен пустой ответ (`$#00'). Таким образом, протокол можно расширять. Новые версии GDB могут определить, поддерживается ли пакет, основываясь на ответе.
От заглушки требуется поддержка команд `g', `G', `m', `M', `c' и `s'. Все остальные команды являются необязательными.
Вот полный список всех определенных на данный момент команд, и соответствующих им ответов данные:
Пакет | Запрос | Описание |
расширенные операции | !
| Использовать расширенный удаленный протокол. Имеет постоянное действие--требует установки только один раз. Расширенный удаленный протокол поддерживает пакеты `R'. |
ответ `' | Заглушки, поддерживающие расширенный удаленный протокол, возвращают `', что, к сожалению, совпадает с ответом, возвращаемым заглушками, которые не поддерживают расширения протокола. | |
последний сигнал | ?
| Указывает причину, по которой цель остановилась. Ответ такой же, как для пошагового выполнения и продолжения. |
ответ | смотрите ниже | |
зарезервировано | a
| Зарезервировано для использования в будущем |
установить аргументы программы (зарезервировано) | A длина-арг, число-арг, арг,...
| |
В программу передается инициализированный массив `argv[]'. Длина-арг задает число байт в закодированном в шестнадцатеричный вид потоке байт арг. Смотрите `gdbserver' для дополнительной информации. | ||
ответ OK
| ||
ответ E NN
| ||
установить скорость (не рекомендовано) | b бод
| Установить скорость последовательной линии в бод. |
установить точку останова (не рекомендовано) | B адрес,режим
| Установить (режим `S') или удалить (режим `C') точку останова по адресу адрес. Это было замещено пакетами `Z' и `z'. |
продолжить | c адрес
| Адрес---это адрес для возобновления выполнения. Если он опущен, возобновить с текущего адреса. |
ответ | смотрите ниже | |
продолжить с сигналом | C сиг; адрес
|
Продолжить с сигналом сиг (шестнадцатеричный номер сигнала). Если
`; адрес' опущено, выполнение возобновляется с прежнего
адреса.
|
ответ | смотрите ниже | |
переключить режим отладки (не рекомендовано) | d
| переключить флаг отладки. |
отсоединиться | D
| Отсоединить GDB от удаленной системы. Посылается удаленной системе перед тем, как GDB отсоединится. |
ответ нет ответа | GDB не ждет никакого ответа после посылки этого пакета. | |
зарезервировано | e
| Зарезервировано для использования в будущем |
зарезервировано | E
| Зарезервировано для использования в будущем |
зарезервировано | f
| Зарезервировано для использования в будущем |
зарезервировано | F
| Зарезервировано для использования в будущем |
чтение регистров | g
| Чтение регистров общего назначения. |
ответ XX... | Каждый байт данных регистра описывается двумя шестнадцатеричными цифрами. Они передаются с целевым порядком байтов. Размер каждого регистра и его позиция внутри пакета `g' определяются внутренними макросами GDB REGISTER_RAW_SIZE и REGISTER_NAME. Спецификация нескольких стандартных пакетов `g' приведена ниже. | |
E NN
| в случае ошибки. | |
запись в регистры | G XX...
| Смотрите `g' для описания данных XX... . |
ответ OK
| в случае успеха | |
ответ E NN
| в случае ошибки | |
зарезервировано | h
| Зарезервировано для использования в будущем |
выбрать нить | H ct...
| Установить нить для последующих операций (`m', `M', `g', `G', и другие). c = `c' для нитей, используемых при пошаговом выполнении и продолжении; t... может быть -1 для всех нитей. c = `g' для нитей, используемых в других операциях. Если ноль--выбрать любую нить. |
ответ OK
| в случае успеха | |
ответ E NN
| в случае ошибки | |
пошаговое выполнение по тактовому циклу (черновик) | i адрес, nnn
|
Выполнить один тактовый цикл на удаленной машине. Если
`, nnn' указано, выполнить nnn циклов. Если
указан адрес, пошаговое выполнение по одному тактовому циклу
начинается этого адреса.
|
сигнал, затем выполнение по тактовым циклам (зарезервировано) | I
| Смотрите `i' и `S', там аналогичный синтаксис и семантика. |
зарезервировано | j
| Зарезервировано для использования в будущем |
зарезервировано | J
| Зарезервировано для использования в будущем |
убить | k
| FIXME: Нет описания, как действовать в случае, если был выбран контекст определенной нити (то есть `k' убивает только эту нить?). |
зарезервировано | l
| Зарезервировано для использования в будущем |
зарезервировано | L
| Зарезервировано для использования в будущем |
чтение памяти | m адрес, длина
| Прочитать длину байт памяти, начиная с адреса адрес. Ни GDB, ни заглушка не предполагают, что передача области памяти происходит по адресам, выровненным по границе слова. FIXME: Нужен механизм передачи области памяти, выровненной по границе слова. |
ответ XX... | XX... представляет собой содержимое памяти. Может содержать меньше запрошенного числа байт, если удалось прочитать только часть данных. Ни GDB, ни заглушка не предполагают, что передача области памяти происходит по адресам, выровненным по границе слова. FIXME: Нужен механизм передачи области памяти, выровненной по границе слова. | |
ответ E NN
| NN представляет номер ошибки | |
запись в память | M адрес,длина: XX...
| Записать длину байт памяти, начиная с адреса адрес. XX...---это данные. |
ответ OK
| при успехе | |
ответ E NN
| при ошибке (это включает случай, когда была записана только часть данных). | |
зарезервировано | n
| Зарезервировано для использования в будущем |
зарезервировано | N
| Зарезервировано для использования в будущем |
зарезервировано | o
| Зарезервировано для использования в будущем |
зарезервировано | O
| Зарезервировано для использования в будущем |
чтение регистров (зарезервировано) | p n...
| Смотрите запись регистров. |
возврат r.... | Значение регистра в целевом порядке байт, закодированное в шестнадцатеричном виде. | |
запись регистров | P n...= r...
| Записать в регистр n... значение r..., которое содержит две шестнадцатеричные цифры для каждого байта в регистре (целевой порядок байтов). |
ответ OK
| в случае успеха | |
ответ E NN
| при ошибке | |
общий запрос | q запрос
| Запросить информацию о запросе. Вообще, запросы GDB имеют первую заглавную букву. Специальные запросы от производителей должны использовать приставку компании (из маленьких букв). Например: `qfsf.var'. За запросом может следовать необязательный список, разделенный `,' или `;'. Заглушки должны проверять, что они производят сравнение с полным именем запроса. |
ответ XX...
| Данные от запроса, закодированные шестнадцатеричными цифрами. Ответ не может быть пустым. | |
ответ E NN
| ответ при ошибке | |
ответ `' | Указывает на нераспознанный запрос. | |
общая установка | Q перем= знач
| Установить значение перем в знач. Смотрите `q' для обсуждения соглашений, касающихся имен. |
сброс (не рекомендовано) | r
| Установка всей системы в исходное состояние. |
удаленная перезагрузка | R XX
| Перезапустить удаленный сервер. XX, где оно требуется, не имеет ясного определения. FIXME: Нужен пример взаимодействия, объясняющий как эти пакеты используются в расширенном удаленном режиме. |
пошагавое выполнение | s адрес
| Адрес---это адрес для возобновления выполнения. Если адрес опущен, возобновить выполнение с того же адреса. |
ответ | смотрите ниже | |
пошаговое выполнение с сигналом | S сиг; адрес
|
Как C , но разница такая же, как между step и
continue .
|
ответ | смотрите ниже | |
поиск | t адрес: PP, MM
| Поиск в обратном направлении, начиная с адреса адрес, до совпадения с шаблоном PP и маской MM. PP и MM---4 байта. Адрес должен быть не менее трех цифр. |
жива ли нить | T XX
| Определить, жива ли нить XX. |
ответ OK
| нить все еще жива | |
ответ E NN
| нить мертва | |
зарезервировано | u
| Зарезервировано для использования в будущем |
зарезервировано | U
| Зарезервировано для использования в будущем |
зарезервировано | v
| Зарезервировано для использования в будущем |
зарезервировано | V
| Зарезервировано для использования в будущем |
зарезервировано | w
| Зарезервировано для использования в будущем |
зарезервировано | W
| Зарезервировано для использования в будущем |
зарезервировано | x
| Зарезервировано для использования в будущем |
запись в память (двоичная) | X адрес, длина:XX...
|
Адрес это адрес, длина это число байт, XX... это
двоичные данные. Символы $ , # и 0x7d экранируются
с помощью 0x7d .
|
ответ OK
| в случае успеха | |
ответ E NN
| в случае ошибки | |
зарезервировано | y
| Зарезервировано для использования в будущем |
зарезервировано | Y
| Зарезервировано для использования в будущем |
удалить точку останова или наблюдения (черновик) | z t, адрес, длина
| Смотрите `Z'. |
поместить точку останова или наблюдения (черновик) | Z t, адрес, длина
| t представляет тип: `0' в случае программной точки останова, `1'---аппаратная точка останова, `2'---точка наблюдения за записью, `3'---точка наблюдения за чтением, `4'---точка наблюдения за доступом; адрес---это адрес; длина задается в байтах. Для программной точки останова, длина задает размер инструкции, на которую надо поместить заплату. Для аппаратных точек останова и наблюдения, длина указывает размер области памяти для наблюдения. Чтобы избежать потенциальных проблем с повторными пакетами, операции должны быть идемпотентным образом. |
ответ E NN
| в случае ошибки | |
ответ OK
| в случае успеха | |
`' | Если не поддерживается. | |
зарезервировано | <другое> | Зарезервировано для использования в будущем |
Пакеты `C', `c', `S', `s' и `?' могут получить в качестве ответа все нижеперечисленное. В случае пакетов `C', `c', `S' и `s', этот ответ возвращается только тогда, когда цель останавливается. Ниже, точное значение `номера сигнала' определено нечетко. Вообще, используется одно из соглашений UNIX о номерах сигналов.
S AA |
AA---это номер сигнала |
T AAn...: r...; n...: r...; n...: r...; |
AA = две шестнадцатеричные цифры номера сигнала; n... =
(шестнадцатеричный) номер регистра, r... = содержимое регистра в
целевом порядке байт, размер определяется REGISTER_RAW_SIZE ;
n... = `thread', r... = идентификатор процесса нити, это
шестнадцатеричное целое; n... = другая строка, не начинающаяся с
шестнадцатеричной цифры. GDB должен игнорировать эту пару
n..., r... и переходить к следующей. Таким образом мы можем
расширять протокол.
|
W AA |
Процесс завершается с кодом выхода AA. Это применимо только к определенным типам целей. |
X AA |
Процесс завершается с сигналом AA. |
N AA; t...; d...; b... (устарело) |
AA = номер сигнала; t... = адрес символа "_start"; d... = база раздела данных; b... = база раздела bss. Примечание: используется только целями Cisco Systems. Разница между этим ответом и запросом "qOffsets" заключается в том, что пакет 'N' может прибыть самопроизвольно, тогда как запрос 'qOffsets' инициируется рабочим отладчиком. |
O XX... |
XX...---шестнадцатеричное представление ASCII-данных. Это может произойти в любой момент, пока программа выполняется и отладчик должен продолжать ждать 'W', 'T', и т.п. |
Следующие пакеты для установок и запросов уже были определены.
текущая нить | q C
| Возвратить идентификатор текущей нити. |
ответ QC идент-проц
| Где идент-проц---16-битный идентификатор процесса, представленный шестнадцатеричнами цифрами. | |
ответ * | Любой другой ответ подразумевает старый идентификатор процесса. | |
идентификаторы всех нитей | q fThreadInfo
| |
q sThreadInfo
|
Получить список идентификаторов активных нитей от целевой ОС. Так как
число активных нитей может оказаться слишком большим и не поместиться в
пакет ответа, этот запрос работает итерациями: он может требовать более
одной последовательности запрос/ответ, для получения полного
списка нитей. Первым запросом последовательности будет
qf ThreadInfo ; последующими запросами последовательности
будут запросы qs ThreadInfo .
| |
Замечание: замещает запрос qL (смотрите ниже).
| ||
ответ m <ид>
| Идентификатор одной нити | |
ответ m <ид>,<ид>...
| список идентификаторов нитей, разделенных запятыми | |
ответ l
| (буква 'l' в нижнем регистре) обозначает конец списка. | |
В ответ на каждый запрос, цель будет отвечать списком из разделенных
запятыми идентификаторов нитей, в шестнадцатеричном представлении, с
порядком байт от старшего. GDB будет отвечать на каждый ответ
запросом других идентификаторов (используя форму qs запроса),
пока цель не ответит l (буква 'l' в нижнем регистре, от
английского слова 'last' ).
| ||
дополнительная информация о нити | q ThreadExtraInfo , ид
| |
Здесь ид является идентификатором нити в шестнадцатеричном представлении, в порядке байт от старшего. Получает печатаемое описание строки атрибутов нити от целевой ОС. Эта строка может содержать все что угодно, что целевая ОС сочтет интересным для GDB сообщить пользователю о нити. Эта строка выводится в отображении GDB `info threads'. Примерами возможной дополнительной информации являются "Runnable" или "Blocked on Mutex". | ||
ответ XX... | Где XX...---ASCII-данные в шестнадцатеричном представлении, содержащие печатную строку с дополнительной информацией об атрибутах нити. | |
запрос список или список-нитей (не рекомендовано) | q L нач-флагчисло-нитейслед-нить
| |
Получить информацию о нити от операционной системы, где происходит выполнение. Здесь: нач-флаг (одна шестнадцатеричная цифра) есть единица, что указывает на первый запрос, или ноль, что определяет последующий запрос; число-нитей (две шестнадцатеричные цифры)---максимальное число нитей, которое может содержать пакет ответа; и след-нить (восемь шестнадцатеричных цифр), для последующих запросов (нач-флаг равен нулю), возвращается в ответ как арг-нить. | ||
Замечание: этот запрос был замещен запросом
q fThreadInfo (смотрите выше).
| ||
ответ q M числоконецарг-нитьнить...
| ||
Здесь: число (две шестнадцатеричные цифры)---число возвращаемых
нитей; конец (одна шестнадцатеричная цифра), есть ноль, который
определяет, что есть еще нити, и единица, определяющая, что
больше нитей нет; арг-нить (восемь шестнадцатеричных цифр)
представляет собой след-нить из пакета запроса;
нить...---это последовательность идентификаторов нитей от цели.
Идент-нити (восемь шестнадцатеричных цифр). Смотрите
remote.c:parse_threadlist_response() .
| ||
вычислить CRC блока памяти | q CRC: адрес, длина
| |
ответ E NN
| Ошибка (например, ошибка доступа к памяти) | |
ответ C CRC32
| Лишняя 32-битная циклическая проверка указанной области памяти. | |
запросить смещения разделов | q Offsets
|
Получить смещения разделов, которые целевая машина использовала при
повторном размещении загруженного образа. Замечание: если
смещение Bss включено в ответ, GDB это игнорирует и
вместо этого применяет к разделу Bss смещение Data .
|
ответ Text= xxx;Data= yyy;Bss= zzz
| ||
запросить информацию о нити | q P режимидент-нити
| |
Возвращает информацию об идент-нити. Здесь: режим является 32-битным режимом в шестнадцатеричном представлении; идент-нити---64-битный идентификатор нити в шестнадцатеричном представлении. | ||
ответ * |
Смотрите remote.c:remote_unpack_thread_info_response() .
| |
удаленная команда | q Rcmd, КОМАНДА
| |
КОМАНДА (в шестнадцатеричном представлении) передается для
выполнения локальному интерпретатору. Неверные команды должны
сообщаться при помощи выходной строки. Перед конечным результирующим
пакетом, целевая машина может также ответить некоторым количеством
промежуточных O ВЫВОД пакетов вывода на консоль.
Разработчики должны учесть, что предоставление доступа к
интерпретатору заглушки может иметь последствия для безопасности.
| ||
ответ OK
| Ответ на команду без вывода. | |
ответ ВЫВОД | Ответ на команду со строкой вывода ВЫВОД, в шестнадцатеричном представлении. | |
ответ E NN
| Указывает на неправильно сформированный запрос. | |
reply `' | Когда `q'`Rcmd' не распознана. |
Следующие пакеты `g'/`G' были определены раньше. Ниже, некоторые 32-битные регистры передаются в виде 64 бит. Эти регистры должны быть расширены нулем/знаком (как?), чтобы заполнять выделенное место. Байты регистра передаются в целевом порядке байтов. Две части в байте регистра передаются от более значимого к менее значимому.
MIPS32 | Все регистры передаются как 32-битные величины в таком порядке: 32 общего назначения; sr; lo; hi; bad; cause; pc; 32 регистра с плавающей точкой; fsr; fir; fp. |
MIPS64 |
Все регистры передаются как 64-битные величины (включая такие 32-битные
регистры, как sr ). Порядок такой же, как для MIPS32 .
|
Вот пример последовательности для перезапускаемой цели. Заметьте, что перезапуск не получает никакого непосредственного вывода:
<-R00
->+
target restarts <-?
->+
->T001:1234123412341234
<-+
Пример последовательности при при пошаговом выполнении цели по одной инструкции:
<-G1445...
->+
<-s
->+
time passes ->T001:1234123412341234
<-+
<-g
->+
->1455...
<-+
13.4.1.5 Использование программы gdbserver
gdbserver
является управляющей программой для Unix-подобных
систем, которая позволяет вам установить соединение вашей программы с
удаленным GDB посредством target remote
, но без
компоновки с обычной отладочной заглушкой.
gdbserver
не является полной заменой отладочных заглушек, потому что
требует по существу тех же средств операционной системы, что и сам
GDB. Фактически, система, на которой может выполняться
gdbserver
для соединения с удаленным GDB, может также
выполнять GDB локально! Тем не менее, gdbserver
иногда
полезен, так как по размеру эта программа гораздо меньше, чем
GDB. gdbserver
также легче переносить, чем
весь GDB, так что вы сможете быстрее начать работать в новой системе,
используя его. Наконец, если вы разрабатываете программы для
систем реального времени, вы можете обнаружить, что накладные расходы,
связанные с операциями реального времени, делают более удобным
проведение всей возможной разработки на другой системе, например, с помощью
кросс-компиляции. Вы можете использовать gdbserver
, чтобы
реализовать аналогичный выбор для отладки.
GDB и gdbserver
общаются или через последовательную
линию, или через соединение TCP, используя стандартный удаленный
последовательный протокол GDB.
- На целевой машине
-
вам необходимо иметь копию программы, которую вы хотите отладить.
gdbserver
не нуждается в таблице символов вашей программы, так что вы можете ее исключить, если необходимо сохранить пространство. Всю обработку символов осуществляет GDB на рабочей машине. Чтобы использовать сервер, вы должны сообщить ему, как взаимодействовать с GDB, имя вашей программы и ее аргументы. Синтаксис следующий:target> gdbserver comm программа [ арг ... ]
comm---это или имя устройства (для использования последовательной линии), или имя рабочей машины и номер порта TCP. Например, для отладки Emacs с параметром `foo.txt' и взаимодействия с GDB через последовательный порт `/dev/com1':target> gdbserver /dev/com1 emacs foo.txt
gdbserver
пассивно ждет рабочего GDB для связи с ним. При использовании TCP-соединения вместо последовательной линии:target> gdbserver host:2345 emacs foo.txt
Единственное отличие от предыдущего примера состоит в первом параметре, определяющем, что вы связываетесь с рабочим GDB через TCP. Параметр `host:2345' означает, чтоgdbserver
должен ожидать TCP-соединение от машины `host' к локальному порту TCP 2345. (В настояшее время часть `host' игнорируется.) Вы можете выбрать любой номер порта, какой захотите, если при этом он не конфликтует с какими-либо портами TCP, уже использующимися на целевой системе (например,23
зарезервирован дляtelnet
).(15) Вы должны использовать тот же номер порта с командой рабочего GDBtarget remote
. - На рабочей машине GDB
-
вам нужна копия вашей программы с символьными данными, так как
GDB нужна информация о символах и отладочная информация.
Запустите GDB как обычно, используя имя локальной копии вашей
программы в качестве первого аргумента. (Вам также может понадобиться
ключ `--baud', если последовательная линия работает на скорости,
отличной от 9600бит/сек.) После этого, используйте
target remote
, чтобы установить связь сgdbserver
. Ее параметры--либо имя устройства (обычно последовательного устройства, такого как `/dev/ttyb'), либо дескриптор порта TCP в формемашина:порт
. Например:(gdb) target remote /dev/ttyb
взаимодействует с сервером через последовательную линию `/dev/ttyb', а(gdb) target remote the-target:2345
взаимодействует через TCP-соединение с портом 2345 на рабочей машине `the-target'. Для TCP-соединения, вы должны запуститьgdbserver
до использования командыtarget remote
. Иначе вы можете получить ошибку, текст которой зависит от рабочей системы, но обычно он выглядит примерно так: `Connection refused'.
13.4.1.6 Использование программы gdbserve.nlm
gdbserve.nlm
---это управляющая программа для систем NetWare,
которая позволяет вам установить соединение вашей программы с
удаленным GDB посредством target remote
.
GDB и gdbserve.nlm
общаются через последовательную линию,
используя стандартный удаленный последовательный протокол GDB.
- На целевой машине
-
вам необходимо иметь копию программы, которую вы хотите отладить.
gdbserve.nlm
не нуждается в таблице символов вашей программы, так что вы можете ее исключить, если необходимо сохранить пространство. GDB осуществляет всю обработку символов на рабочей машине. Чтобы использовать сервер, вы должны сообщить ему как взаимодействовать с GDB, имя вашей программы и ее аргументы. Синтаксис следующий:load gdbserve [ BOARD=плата ] [ PORT=порт ] [ BAUD=бод ] программа [ арг ... ]
Плата и порт определяют последовательную линию; бод определяет скорость в бодах, используемую соединением. Значения порт и node по умолчанию равны 0, бод по умолчанию 9600бит/сек. Например, для отладки Emacs с параметром `foo.txt' и взаимодействия с GDB через последовательный порт номер 2 на плате 1, используя соединение 19200бит/сек:load gdbserve BOARD=1 PORT=2 BAUD=19200 emacs foo.txt
- На рабочей машине GDB
-
вам нужна копия вашей программы с символьными данными, так как
GDB требуется символьная и отладочная информация. Запустите
GDB как обычно, используя имя локальной копии вашей программы в
качестве первого параметра. (Вам также может понадобиться ключ
`--baud', если последовательная линия работает на скорости,
отличной от 9600бит/сек.) После этого, используйте
target remote
для установки связи сgdbserve.nlm
. Ее аргумент--имя устройства (обычно последовательного устройства, такого как `/dev/ttyb'). Например:(gdb) target remote /dev/ttyb
соединение с сервером через последовательную линию `/dev/ttyb'.
13.5 Отображение объектов ядра
Некоторые цели поддерживают отображение объектов ядра. При помощи этих возможностей, GDB взаимодействует непосредственно с операционной системой и может выводить информацию об объектах уровня операционной системы, например, о блокировках и других объектах синхронизации. Какие именно объекты могут быть отображены, определяется в зависимости от конкретной ОС.
Используйте команду set os
, чтобы установить тип операционной
системы. Это говорит GDB, какой модуль отображения объектов
ядра инициализировать:
(gdb) set os cisco
Если команда set os
выполнится успешно, GDB выведет
некоторую информацию об операционной системе, и создаст новую команду
info
, которая может быть использована для посылки запросов на
целевую машину. Название команды info
выбирается в зависимости
от операционной системы:
(gdb) info cisco List of Cisco Kernel Objects Object Description any Any and all objects
Дальнейшие подкоманды могут использоваться для запросов о конкретных объектах, информация о которых есть в ядре.
В настоящее время не существует другого способа определить, поддерживается та или иная операционная система, кроме как попробовать.
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]