Отладка с помощью 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.

См. раздел 12.1 Команды для задания файлов.
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 Встроенные процессоры.

Некоторые конфигурации могут также включать такие цели:

target nrom устр
Эмулятор NetROM ROM. Эта цель поддерживает только загрузку.

Для различных конфигураций 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

Для отладки программы, выполняемой на другой машине (отладочной целевой машине), вы сперва должны создать все обычные предпосылки для самостоятельного выполнения программы. Например, для программы на Си вам нужны:

  1. Процедура запуска для установки среды выполнения Си; она обычно имеет имя типа `crt0'. Процедура запуска может быть обеспечена вашими аппаратными средствами, или вы должны написать свою собственную.
  2. Библиотека подпрограмм Си для поддержки вызовов подпрограмм вашей программы, особенно для управления вводом и выводом.
  3. Способ установки вашей программы на другую машину--например, программа загрузки. Такие программы часто предоставляются поставщиками аппаратных средств, но вам может потребоваться написать вашу собственную, пользуясь документацией к аппаратному обеспечению.

Следующим шагом будет принятие мер по использованию вашей программой последовательного порта для связи с машиной, где выполняется 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 Собираем все вместе

Вкратце, когда ваша программа готова к отладке, вы должны проделать следующие шаги.

  1. Убедитесь, что вы определили поддерживающие процедуры низкого уровня (см. раздел 13.4.1.2 Что вы должны сделать для заглушки):
    getDebugChar, putDebugChar,
    flush_i_cache, memset, exceptionHandler.
    
  2. Вставьте следующие строки в начале вашей программы:
    set_debug_traps();
    breakpoint();
    
  3. Для заглушки 680x0, вы должны предоставить переменную exceptionHook. Обычно вы используете просто:
    void (*exceptionHook)() = 0;
    
    если до вызова set_debug_traps вы установили ее для указания на функцию в вашей программе. Эта функция вызывается, когда GDB продолжает выполнение после останова на ловушке (например, ошибка шины). Функция, указанная exceptionHook, вызывается с одним параметром типа int, который является номером исключения.
  4. Откомпилируйте и скомпонуйте вместе: вашу программу, отладочную заглушку GDB для вашей целевой архитектуры и подпрограммы поддержки.
  5. Убедитесь, что у вас есть последовательное соединение между вашей целевой и рабочей машинами, и идентифицируйте последовательный порт на рабочей машине.
  6. Загрузите вашу программу на целевую машину (или поместите ее туда любыми средствами, предоставляемыми производителем) и запустите ее.
  7. Для начала удаленной отладки, запустите GDB на рабочей машине и укажите в качестве выполняемого файла программу, которая выполняется на удаленной машине. Это сообщает GDB, как найти символы и содержание неизменяемых областей вашей программы.
  8. Установите связь, используя команду 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
ответ ENN
установить скорость (не рекомендовано) 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' приведена ниже.
ENN в случае ошибки.
запись в регистры GXX... Смотрите `g' для описания данных XX... .
ответ OK в случае успеха
ответ ENN в случае ошибки
зарезервировано h Зарезервировано для использования в будущем
выбрать нить Hct... Установить нить для последующих операций (`m', `M', `g', `G', и другие). c = `c' для нитей, используемых при пошаговом выполнении и продолжении; t... может быть -1 для всех нитей. c = `g' для нитей, используемых в других операциях. Если ноль--выбрать любую нить.
ответ OK в случае успеха
ответ ENN в случае ошибки
пошаговое выполнение по тактовому циклу (черновик) iадрес,nnn Выполнить один тактовый цикл на удаленной машине. Если `,nnn' указано, выполнить nnn циклов. Если указан адрес, пошаговое выполнение по одному тактовому циклу начинается этого адреса.
сигнал, затем выполнение по тактовым циклам (зарезервировано) I Смотрите `i' и `S', там аналогичный синтаксис и семантика.
зарезервировано j Зарезервировано для использования в будущем
зарезервировано J Зарезервировано для использования в будущем
убить k FIXME: Нет описания, как действовать в случае, если был выбран контекст определенной нити (то есть `k' убивает только эту нить?).
зарезервировано l Зарезервировано для использования в будущем
зарезервировано L Зарезервировано для использования в будущем
чтение памяти mадрес,длина Прочитать длину байт памяти, начиная с адреса адрес. Ни GDB, ни заглушка не предполагают, что передача области памяти происходит по адресам, выровненным по границе слова. FIXME: Нужен механизм передачи области памяти, выровненной по границе слова.
ответ XX... XX... представляет собой содержимое памяти. Может содержать меньше запрошенного числа байт, если удалось прочитать только часть данных. Ни GDB, ни заглушка не предполагают, что передача области памяти происходит по адресам, выровненным по границе слова. FIXME: Нужен механизм передачи области памяти, выровненной по границе слова.
ответ ENN NN представляет номер ошибки
запись в память Mадрес,длина:XX... Записать длину байт памяти, начиная с адреса адрес. XX...---это данные.
ответ OK при успехе
ответ ENN при ошибке (это включает случай, когда была записана только часть данных).
зарезервировано n Зарезервировано для использования в будущем
зарезервировано N Зарезервировано для использования в будущем
зарезервировано o Зарезервировано для использования в будущем
зарезервировано O Зарезервировано для использования в будущем
чтение регистров (зарезервировано) pn... Смотрите запись регистров.
возврат r.... Значение регистра в целевом порядке байт, закодированное в шестнадцатеричном виде.
запись регистров Pn...=r... Записать в регистр n... значение r..., которое содержит две шестнадцатеричные цифры для каждого байта в регистре (целевой порядок байтов).
ответ OK в случае успеха
ответ ENN при ошибке
общий запрос qзапрос Запросить информацию о запросе. Вообще, запросы GDB имеют первую заглавную букву. Специальные запросы от производителей должны использовать приставку компании (из маленьких букв). Например: `qfsf.var'. За запросом может следовать необязательный список, разделенный `,' или `;'. Заглушки должны проверять, что они производят сравнение с полным именем запроса.
ответ XX... Данные от запроса, закодированные шестнадцатеричными цифрами. Ответ не может быть пустым.
ответ ENN ответ при ошибке
ответ `' Указывает на нераспознанный запрос.
общая установка Qперем=знач Установить значение перем в знач. Смотрите `q' для обсуждения соглашений, касающихся имен.
сброс (не рекомендовано) r Установка всей системы в исходное состояние.
удаленная перезагрузка RXX Перезапустить удаленный сервер. XX, где оно требуется, не имеет ясного определения. FIXME: Нужен пример взаимодействия, объясняющий как эти пакеты используются в расширенном удаленном режиме.
пошагавое выполнение sадрес Адрес---это адрес для возобновления выполнения. Если адрес опущен, возобновить выполнение с того же адреса.
ответ смотрите ниже
пошаговое выполнение с сигналом Sсиг;адрес Как C, но разница такая же, как между step и continue.
ответ смотрите ниже
поиск tадрес:PP,MM Поиск в обратном направлении, начиная с адреса адрес, до совпадения с шаблоном PP и маской MM. PP и MM---4 байта. Адрес должен быть не менее трех цифр.
жива ли нить TXX Определить, жива ли нить XX.
ответ OK нить все еще жива
ответ ENN нить мертва
зарезервировано u Зарезервировано для использования в будущем
зарезервировано U Зарезервировано для использования в будущем
зарезервировано v Зарезервировано для использования в будущем
зарезервировано V Зарезервировано для использования в будущем
зарезервировано w Зарезервировано для использования в будущем
зарезервировано W Зарезервировано для использования в будущем
зарезервировано x Зарезервировано для использования в будущем
запись в память (двоичная) Xадрес,длина:XX... Адрес это адрес, длина это число байт, XX... это двоичные данные. Символы $, # и 0x7d экранируются с помощью 0x7d.
ответ OK в случае успеха
ответ ENN в случае ошибки
зарезервировано y Зарезервировано для использования в будущем
зарезервировано Y Зарезервировано для использования в будущем
удалить точку останова или наблюдения (черновик) zt,адрес,длина Смотрите `Z'.
поместить точку останова или наблюдения (черновик) Zt,адрес,длина t представляет тип: `0' в случае программной точки останова, `1'---аппаратная точка останова, `2'---точка наблюдения за записью, `3'---точка наблюдения за чтением, `4'---точка наблюдения за доступом; адрес---это адрес; длина задается в байтах. Для программной точки останова, длина задает размер инструкции, на которую надо поместить заплату. Для аппаратных точек останова и наблюдения, длина указывает размер области памяти для наблюдения. Чтобы избежать потенциальных проблем с повторными пакетами, операции должны быть идемпотентным образом.
ответ ENN в случае ошибки
ответ OK в случае успеха
`' Если не поддерживается.
зарезервировано <другое> Зарезервировано для использования в будущем

Пакеты `C', `c', `S', `s' и `?' могут получить в качестве ответа все нижеперечисленное. В случае пакетов `C', `c', `S' и `s', этот ответ возвращается только тогда, когда цель останавливается. Ниже, точное значение `номера сигнала' определено нечетко. Вообще, используется одно из соглашений UNIX о номерах сигналов.

SAA AA---это номер сигнала
TAAn...:r...;n...:r...;n...:r...; AA = две шестнадцатеричные цифры номера сигнала; n... = (шестнадцатеричный) номер регистра, r... = содержимое регистра в целевом порядке байт, размер определяется REGISTER_RAW_SIZE; n... = `thread', r... = идентификатор процесса нити, это шестнадцатеричное целое; n... = другая строка, не начинающаяся с шестнадцатеричной цифры. GDB должен игнорировать эту пару n..., r... и переходить к следующей. Таким образом мы можем расширять протокол.
WAA Процесс завершается с кодом выхода AA. Это применимо только к определенным типам целей.
XAA Процесс завершается с сигналом AA.
NAA;t...;d...;b... (устарело) AA = номер сигнала; t... = адрес символа "_start"; d... = база раздела данных; b... = база раздела bss. Примечание: используется только целями Cisco Systems. Разница между этим ответом и запросом "qOffsets" заключается в том, что пакет 'N' может прибыть самопроизвольно, тогда как запрос 'qOffsets' инициируется рабочим отладчиком.
OXX... XX...---шестнадцатеричное представление ASCII-данных. Это может произойти в любой момент, пока программа выполняется и отладчик должен продолжать ждать 'W', 'T', и т.п.

Следующие пакеты для установок и запросов уже были определены.

текущая нить qC Возвратить идентификатор текущей нити.
ответ QCидент-проц Где идент-проц---16-битный идентификатор процесса, представленный шестнадцатеричнами цифрами.
ответ * Любой другой ответ подразумевает старый идентификатор процесса.
идентификаторы всех нитей qfThreadInfo
qsThreadInfo Получить список идентификаторов активных нитей от целевой ОС. Так как число активных нитей может оказаться слишком большим и не поместиться в пакет ответа, этот запрос работает итерациями: он может требовать более одной последовательности запрос/ответ, для получения полного списка нитей. Первым запросом последовательности будет qfThreadInfo; последующими запросами последовательности будут запросы qsThreadInfo.
Замечание: замещает запрос qL (смотрите ниже).
ответ m<ид> Идентификатор одной нити
ответ m<ид>,<ид>... список идентификаторов нитей, разделенных запятыми
ответ l (буква 'l' в нижнем регистре) обозначает конец списка.
В ответ на каждый запрос, цель будет отвечать списком из разделенных запятыми идентификаторов нитей, в шестнадцатеричном представлении, с порядком байт от старшего. GDB будет отвечать на каждый ответ запросом других идентификаторов (используя форму qs запроса), пока цель не ответит l (буква 'l' в нижнем регистре, от английского слова 'last').
дополнительная информация о нити qThreadExtraInfo,ид
Здесь ид является идентификатором нити в шестнадцатеричном представлении, в порядке байт от старшего. Получает печатаемое описание строки атрибутов нити от целевой ОС. Эта строка может содержать все что угодно, что целевая ОС сочтет интересным для GDB сообщить пользователю о нити. Эта строка выводится в отображении GDB `info threads'. Примерами возможной дополнительной информации являются "Runnable" или "Blocked on Mutex".
ответ XX... Где XX...---ASCII-данные в шестнадцатеричном представлении, содержащие печатную строку с дополнительной информацией об атрибутах нити.
запрос список или список-нитей (не рекомендовано) qLнач-флагчисло-нитейслед-нить
Получить информацию о нити от операционной системы, где происходит выполнение. Здесь: нач-флаг (одна шестнадцатеричная цифра) есть единица, что указывает на первый запрос, или ноль, что определяет последующий запрос; число-нитей (две шестнадцатеричные цифры)---максимальное число нитей, которое может содержать пакет ответа; и след-нить (восемь шестнадцатеричных цифр), для последующих запросов (нач-флаг равен нулю), возвращается в ответ как арг-нить.
Замечание: этот запрос был замещен запросом qfThreadInfo (смотрите выше).
ответ qMчислоконецарг-нитьнить...
Здесь: число (две шестнадцатеричные цифры)---число возвращаемых нитей; конец (одна шестнадцатеричная цифра), есть ноль, который определяет, что есть еще нити, и единица, определяющая, что больше нитей нет; арг-нить (восемь шестнадцатеричных цифр) представляет собой след-нить из пакета запроса; нить...---это последовательность идентификаторов нитей от цели. Идент-нити (восемь шестнадцатеричных цифр). Смотрите remote.c:parse_threadlist_response().
вычислить CRC блока памяти qCRC:адрес,длина
ответ ENN Ошибка (например, ошибка доступа к памяти)
ответ CCRC32 Лишняя 32-битная циклическая проверка указанной области памяти.
запросить смещения разделов qOffsets Получить смещения разделов, которые целевая машина использовала при повторном размещении загруженного образа. Замечание: если смещение Bss включено в ответ, GDB это игнорирует и вместо этого применяет к разделу Bss смещение Data.
ответ Text=xxx;Data=yyy;Bss=zzz
запросить информацию о нити qPрежимидент-нити
Возвращает информацию об идент-нити. Здесь: режим является 32-битным режимом в шестнадцатеричном представлении; идент-нити---64-битный идентификатор нити в шестнадцатеричном представлении.
ответ * Смотрите remote.c:remote_unpack_thread_info_response().
удаленная команда qRcmd,КОМАНДА
КОМАНДА (в шестнадцатеричном представлении) передается для выполнения локальному интерпретатору. Неверные команды должны сообщаться при помощи выходной строки. Перед конечным результирующим пакетом, целевая машина может также ответить некоторым количеством промежуточных OВЫВОД пакетов вывода на консоль. Разработчики должны учесть, что предоставление доступа к интерпретатору заглушки может иметь последствия для безопасности.
ответ OK Ответ на команду без вывода.
ответ ВЫВОД Ответ на команду со строкой вывода ВЫВОД, в шестнадцатеричном представлении.
ответ ENN Указывает на неправильно сформированный запрос.
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) Вы должны использовать тот же номер порта с командой рабочего GDB target 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

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

В настоящее время не существует другого способа определить, поддерживается та или иная операционная система, кроме как попробовать.


[Содержание]   [Назад]   [Пред]   [Вверх]   [След]   [Вперед]