Применение GDB

Статья охватывает особенности использования отладчика

Оглавление:

Специфичные для Нейтрино расширения
Краткая инструкция по запуску отладчика
Команды GDB
Синтаксис команд
Подсказки для команд
Получение справки
Запуск программ под управлением отладчика
Компиляция для отладки
Задание целевой платформы
Запуск вашей программы
Аргументы вашей программы
Среда окружения вашей программы
Ввод и вывод вашей программы
Отладка уже запущенного процесса
Уничтожение отлаживаемого процесса
Отладка программ с несколькими потоками
Отладка программ с дочерними процессами
Остановка и продолжение исполнения
Точки останова, точки наблюдения и исключения
Установка точек останова
Установка точек наблюдения
Точки останова и исключения
Удаление точек останова
Отключение точек останова
Условия останова
Список команд точки останова
Меню точки останова
Продолжение и выполнение по шагам
Сигналы
Остановка и запуск многопоточных программ
Проверка стека
Кадры стека
Цепочки вызовов
Выбор кадра
Информация о кадре
MIPS-машины и стек функции
Проверка файлов с исходными текстами
Вывод строк исходного текста
Поиск в исходных файлах
Определение каталогов с исходными файлами
Исходный текст и машинный код
Разделяемые библиотеки
Проверка данных
Выражения
Переменные программы
Искусственные массивы
Форматы вывода
Проверка памяти
Автоматическое отображение
Параметры вывода
История значений
Вспомогательные переменные
Регистры
Аппаратные средства поддержки вычислений с плавающей точкой
Проверка символьной таблицы
Изменение исполнения
Присваивание значений пеpеменным
Продолжение исполнения с другого адреса
Подача сигнала вашей программе
Возврат из функции
Вызов функций программы
Внесение изменений в программу

Специфичные для Нейтрино расширения

Реализация GDB для Нейтрино включает в себя следующие расширения:

target qnx
Задать целевую платформу; см. Задание целевой платформы.
set nto-inherit-env
Задать откуда удаленный процесс наследует среду окружения; см Среда окружения вашей программы.
set nto-cwd
Задать рабочую директорию для удаленного процесса; см. Запуск вашей программы.
set nto-timeout
Задать тайм-аут для удаленного чтения; см. Задание целевой платформы.
upload local_path remote_path
Отправить файл на удаленную целевую систему.
download remote_path local_path
Принять файл с удаленной целевой системы.
info pidlist
Отобразить список процессов и их идентификационный номера процессов на удаленной целевой системе.
info meminfo
Отобразить список областей памяти (общих объектов) для текущего отлаживаемого процесса.

Краткая инструкция по запуску отладчика

Для отладки приложения выполните следующие команды:

  1. Запустите GDB, не указывая приложение в качестве аргумента:

    gdb

  2. Загрузите символьную информацию для приложения:

    file my_application

  3. Если вы выполняете отладку удаленно, задайте целевую платформу:

    target qnx com_port_specifier | host:port | pty

  4. Если вы выполняете отладку удаленно, отправьте приложение на целевую платформу:

    upload my_application /tmp/my_application

  5. Задайте точки останова. Например, задание точки останова в функции main():

    set break main

  6. Запустите приложение:

    run

Команды GDB

Вы можете сократить команду GDB до нескольких первых букв имени команды, если это сокращение однозначно; и вы можете повторять выполнение определенных команд GDB, просто нажав Enter. Вы также можете использовать клавишу Tab, чтобы GDB заполнял оставшуюся часть слова в команде (или чтобы показать вам доступные альтернативы, если они есть).

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

Синтаксис команд

Команда GDB - это одна строка, подающаяся на ввод. Нет никаких ограничений на то, какой длины она может быть. Строка начинается с имени команды, за которым следуют аргументы, значение которых зависит от имени команды. Например, команда step принимает аргумент, который представляет собой количество шагов, которые выполняются программой, пример: step 5. Вы также можете использовать команду step без аргументов. Некоторые имена команд не допускают никаких аргументов.

Имена команд GDB всегда могут быть сокращены, если это сокращение однозначно. Другие возможные сокращения команд перечислены в документации для отдельных команд. В некоторых случаях разрешены даже двусмысленные сокращения; например, s специально определяется как эквивалент step, хотя есть другие команды, имена которых начинаются с s. Вы можете проверить сокращения, используя их в качестве аргументов команды help.

Пустая строка в качестве входных данных для GDB (ввод просто Enter) означает повторение предыдущей команды. Некоторые команды (например, run) таким образом не повторяются; это команды, непреднамеренное повторение которых может вызвать проблемы и которые вы вряд ли захотите повторять.

Команды list и x, при их повторе нажатием Enter, вместо точного повтора создают новые параметры. Это позволяет легко просматривать исходный текст или память.

GDB может также использовать Enter по-другому: для разделения длинных выходных данных способом, похожим на утилиту more. Так как в этой ситуации легко выполнить непреднамеренный повторный ввод команды Enter, GDB запрещает повторение команд после любой команды, которая генерирует такой вид отображения.

Любой текст от # до конца строки является комментарием. Это полезно в основном в командных файлах.

Подсказки для команд

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

Нажимите клавишу Tab, если вы хотите, чтобы GDB заполнил оставшуюся часть слова. Если есть только однин вариант подсказки, GDB подставляет подсказку и ждет, пока вы завершите команду (или нажмете Enter, чтобы ввести ее). Например, если вы наберете:

(gdb) info bre Tab

GDB заполнит оставшиеся символы в слове breakpoints, поскольку это единственная подкоманда команды info, начинающаяся с bre:

(gdb) info breakpoints

Вы можете либо нажать Enter, чтобы запустить команду info breakpoints, либо Backspace, чтобы ввести что-нибудь еще, если подстановка breakpoints не похожа на то, что вы ожидали. (Если вы были уверены, что вам нужна была команда info breakpoints, вы могли просто нажать Enter сразу после info bre, чтобы использовать сокращение команды, а не полное название команды).

Если при нажатии Tab есть несколько возможностей подсказки для следующего слова, GDB подает сигнал. Вы можете ввести больше символов и попробовать еще раз или просто нажать Tab второй раз; GDB отобразит все возможные варианты завершения для этого слова. Например, вы можете захотеть установить точку останова для подпрограммы, имя которой начинается с make_, но когда вы наберете:

b make_Tab

GDB просто подаст сигнал. При вводе Tab снова отображаются все имена функций в вашей программе, которые начинаются с этих символов, например:

make_a_section_from_file make_environ make_abs_section make_function_type make_blockvector make_pointer_type make_cleanup make_reference_type make_command make_symbol_completion_list (gdb) b make_

После отображения доступных подсказок GDB копирует ваш частичный ввод (b make_ в примере), чтобы вы могли завершить команду.

Если вы просто хотите сначала увидеть список альтернатив, вы можете нажать Esc, а затем ? (вместо того, чтобы дважды нажимать Tab).

Иногда нужная вам строка, являясь логически «словом», может содержать круглые скобки или другие символы, которые GDB обычно исключает из своего понятия слова. Чтобы разрешить автозавершение слов в этой ситуации, вы можете заключить слова в ' (одинарные кавычки) в командах GDB.

Наиболее вероятная ситуация, когда вам это может понадобиться, - это ввод имени функции C++. Это связано с тем, что C++ допускает перегрузку функций (несколько определений одной и той же функции, различающиеся по типу аргумента). Например, когда вы хотите установить точку останова, вам может потребоваться различить, имеете ли вы в виду версию команду name, которая принимает параметр int, name (int), или версию, которая принимает параметр float, name (float). Чтобы использовать в этой ситуации средства завершения слов, введите одинарную кавычку ' в начале имени функции. В таком случае GDB поймет, что ему может потребоваться рассмотреть больше информации, чем обычно, когда вы нажимаете Tab или Esc с последующим ?, чтобы запросить завершение слова:

(gdb) b 'bubble(Esc? bubble(double,double) bubble(int,int) (gdb) b 'bubble(

В некоторых случаях GDB может вывести сообщение о том, что завершение имени требует использования кавычек. Когда это происходит, GDB вставляет кавычку за вас (при этом заполняя столько, сколько может), если вы не вводите кавычку с самого начала:

(gdb) b bub Tab

GDB изменяет вашу строку ввода на следующую и подает сигнал:

(gdb) b 'bubble(

В общем, GDB может показать, что кавычка необходима (и вставить ее), если вы еще не начали вводить список аргументов, когда вы запрашиваете завершение для перегруженного символа.

Получение справки

Вы всегда можете запросить информацию о командах у самого GDB, используя команду help.

help
h
Вы можете использовать help (или h) без аргументов, чтобы отобразить короткий список имен классов команд:
(gdb) help List of classes of commands: running -- Running the program stack -- Examining the stack data -- Examining data breakpoints -- Making program stop at certain points files -- Specifying and examining files status -- Status inquiries support -- Support facilities user-defined -- User-defined commands aliases -- Aliases of other commands obscure -- Obscure features Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb)
help class
Используя имя класса команд справки в качестве аргумента, вы можете получить список отдельных команд в этом классе. Например, вот справочная информация о классе status:
(gdb) help status Status inquiries. List of commands: show -- Generic command for showing things set with "set" info -- Generic command for printing status Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb)
help command
С именем команды в качестве аргумента справки GDB отображает короткий абзац о том, как использовать эту команду.
complete args
Команда complete args перечисляет все возможные варианты завершения для начала команды. Вместо args, введите начало команды, которую вы хотите выполнить. Например:
complete i

Приведет к выводу:
info inspect ignore

Подобную команду можно увидеть во всех текстовых редакторах семейства GNU Emacs

Помимо команды help, вы также можете использовать GDB-команды info и show, чтобы узнать о состоянии вашей программы или о состоянии самого GDB. Каждая команда поддерживает множество возможностей для применения; это руководство представляет каждый из них в соответствующем контексте. Списки из info и show могут указывть на подкоманды.

info
Эта команда (сокращенно i) предназначена для описания состояния вашей программы. Например, вы можете перечислить аргументы, переданные вашей программе, с помощью команды info args, перечислить регистры, используемые в настоящее время, с помощью команды info registers или перечислить точки останова, которые вы установили, с помощью команды info breakpoints. Вы можете получить полный список подкоманд info с помощью команды help info.
set
Вы можете присвоить результат выражения переменной среды с помощью set. Например, вы можете присвоить результат вызова GDB-команды promt на знак $ с помощью команды set prompt $.
show
В отличие от info, show предназначено для описания состояния самого GDB. Вы можете изменить большинство вещей, которые могут выводится командой show, используя команду set; например, вы можете установить, какая система счисления будет используется для отображения с помощью команды set radix, или просто узнать, какая система счисления используется в настоящее время с помощью команды show radix.

Чтобы отобразить все настраиваемые параметры и их текущие значения, вы можете использовать show без аргументов; вы также можете использовать набор информации. Обе команды производят одинаковый дисплей.

Вот три разных подкоманды show, каждая из которых является исключением из-за отсутствия аналогов для команды set:

show version
Вывод версии GDB, которая работает в данный момент. Вам следует включать эту информацию в отчеты об ошибках GDB. Если на вашем сайте используется несколько версий GDB, вам может пригодиться возможность определять какую версию GDB вы используете; по мере развития в перечень команд GDB вводятся новые команды, а старые могут исчезнуть. Номер версии также выводится при запуске GDB.
show copying
Вывести информацию о разрешении на копирование GDB.
show warranty
Вывести заявление об отсутствии гарантии: GNU "NO WARRANTY".

Запуск программ под управлением отладчика

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

Компиляция для отладки

Отладочная информация сохраняется в объектном файле; она описывает тип данных каждой переменной или функции, и соответствие между номерами строк исходного текста и адресами в выполняемом коде.

Чтобы запросить генерацию отладочной информации, укажите опцию -g при вызове компилятора.

GCC, GNU компилятор языка С, поддерживает опцию -g с или без опции -O, делая возможным отладку оптимизированного кода. Мы рекомендуем, чтобы вы всегда использовали -g при компиляции программ. Вы можете думать, что ваша программа правильная, но нет никакого смысла испытывать удачу.

Когда вы отлаживаете программу, откомпилированную с помощью оцпий -g -O, помните, что оптимизатор перестраивает ваш код; отладчик же показывает то, что там находится в действительности. Не удивляйтесь, если порядок выполнения не будет в точности соответствовать вашему исходному файлу! Например: если вы определяете переменную, но нигде ее не используете, GDB никогда не увидит этой переменной, потому что при оптимизации компилятор ее исключит.

Некоторые вещи не работают с опциями -g -O также, как просто с опцией -g, в частности, на машинах с планированием инструкций. Если сомневаетесь, перекомпилируйте программу используя только опцию -g, и если это устранит проблему, пожалуйста, сообщите нам об этом как об ошибке (не забудьте включить в отчет тестовый пример!).

Задание целевой платформы

Если вы занимаетесь отладкой локально, то вам не нужно указывать целевую платформу (или вы можете указать целевую procfs).

Если вы занимаетесь отладкой удаленно, то вам нужно указать целевую платформу для использования:

target qnx com_port_specifier | host:port | pty

Опция pty запускает сервер pdebug на локальной машине и подключается к нему через pty.


Note: Менеджер devc-pty должен быть запущен на машине, на которой запущен pdebug, и пара ptyp/ttyp должна быть доступной.

Запуск вашей программы

set nto-cwd path
Указать рабочую деректорию удаленного процесса. Вы должны сделать это перед запуском вашей программы.
run
r
Используйте команду run для запуска вашей программы под управлением GDB. Сначала вы должны задать имя программы с помощью аргумента GDB (см. описание утилиты gdb).

run создает подчиненный процесс, и этот процесс выполняет вашу программу.

Выполнение программы зависит от определенной информации, которую она получает от породившего ее процесса. GDB предоставляет способы задать эту информацию, что вы должны сделать до запуска программы. (Вы можете изменить ее после запуска, но такие изменения воздействуют на вашу программу только при следующем запуске.) Эта информация может быть разделена категории:

Аргументы
Задайте аргументы, которые нужно передать вашей программе, как аргументы команды run. Если на вашей системе доступна оболочка, она используется для передачи аргументов, так что при их описании вы можете использовать обычные соглашения (такие как раскрывание шаблонов или подстановка переменных). В системах Unix, вы можете контролировать, какая оболочка используется, с помощью переменной среды SHELL. См. Аргументы вашей программы.
Среда окружения
Обычно ваша программа наследует свою среду от GDB, но вы можете использовать команды GDB set environment и unset environment, чтобы изменить часть настроек среды, влияющих на вашу программу. См. Среда окружения вашей программы.


Note: Пока работает перенаправление ввода и вывода, вы не можете использовать каналы (pipe) для передачи вывода отлаживаемой программы другой программе; если вы попытаетесь это сделать, GDB, скорее всего, выполнит отладку не той программы.

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

Пример запуска программы для локальной отладки:

(gdb) file /tmp/helloworld Reading symbols from /tmp/helloworld...done. (gdb) b main Breakpoint 1 at 0x804860c: file ./main.c, line 5. (gdb) r Starting program: Remote: /tmp/helloworld Breakpoint 1, main () at ./main.c:5 5 { (gdb)

Пример запуска программы для удаленной отладки:

(gdb) target qnx mytst:8000 Remote debugging using mytst:8000 Remote target is little-endian (gdb) file /tmp/helloworld Reading symbols from /tmp/helloworld...done. (gdb) upload /tmp/helloworld /tmp/helloworld (gdb) b main Breakpoint 1 at 0x804860c: file ./main.c, line 5. (gdb) r Starting program: Remote: /tmp/helloworld Breakpoint 1, main () at ./main.c:5 5 { (gdb)

Если ваша линия связи медленная, вам может потребоваться установить тайм-аут для удаленного чтения:

set nto-timeout time

где time это время ожидания в секундах. По умолчанию - 10 секунд.

Аргументы вашей программы

Аргументы к вашей программе могут быть заданы с помощью аргументов команды run.

Команда run без аргументов использует те же аргументы, которые использовались предыдущим запуском команды run, или те, которые были заданы командой set args.

set args
Задает аргументы, которые будут использоваться при следующем запуске вашей программы. Если у set args нет аргументов, run выполняет вашу программу без аргументов. Если вы запустили вашу программу с аргументами, то единственный способ запустить ее снова без аргументов - это использовать set args перед следующим запуском программы командой run.
show args
Показать аргументы, которые будут переданы вашей программе при ее запуске.

Среда окружения вашей программы

Среда окружения состоит из набора переменных среды и их значений. Переменные окружения обычно хранят такие данные, как ваше имя пользователя, домашний каталог, тип терминала и путь поиска для запуска программ. Как правило, вы устанавливаете переменные окружения с помощью оболочки и они наследуются всеми другими программами, которые вы запускаете. При отладке может оказаться полезным попробовать запустить программу в измененной среде, не перезапуская GDB.

set nto-inherit-env value
Если значение равно 0, процесс наследует свое окружение от GDB. Если значение равно 1 (по умолчанию), процесс наследует свою среду от pdebug.
path directory
Добавить каталог в начало переменной среды PATH (пути поиска исполняемых файлов), как для GDB, так и для вашей программы. Вы можете указать названия нескольких каталогов, разделив их пробелом или двоеточием (:). Если directory (каталог) уже находится в списке путей, он переносится в начало, так что поиск в нем будет производиться раньше. Вы можете использовать строку $cwd, чтобы сослаться на рабочий каталог, который является текущим в тот момент, когда GDB производит поиск. Если вместо этого вы используете (.), то она будет ссылаться на тот каталог, в котором вы выполнили команду path. GDB заменяет (.) в аргументе directory на текущий путь до добавления directory к списку путей поиска.
show paths
Отобразить список путей для поиска выполняемых файлов (переменную среды PATH).
show environment [varname]
Вывести значение переменной среды (varname), которое будет передано вашей программе при ее старте. Если вы не указываете varname, то данная команда выводит названия и значения всех переменных среды, передаваемых вашей программе. Вы можете сократить environment как env.
set environment varname [=] value
Присваивает значение value переменной среды varname. Значение меняется только для вашей программы, но не для самого GDB. значение value может быть любой строкой; значениями переменных среды являются просто строки, а их интерпретацию обеспечивает ваша программа. Параметр value является необязательным; если он пропущен, переменная устанавливается в пустое значение. Например эта команда:

set env USER = foo

говорит отлаживаемой программе, что при последующих запусках именем пользователя является foo.
unset environment varname
Удалить переменную varname из среды, передаваемой вашей программе. Это отличается от set env varname = ; unset environment удаляет переменную из среды, а не присваивает ей пустое значение.

Ввод и вывод вашей программы

По умолчанию, программа, которую вы запускаете под управлением GDB, осуществляет ввод и вывод на тот же терминал, что и GDB. Для взаимодействия с вами, GDB переключает терминал в свой собственный терминальный режим, но он записывает терминальные режимы, которые использовала ваша программа, и переключается назад к ним, когда вы продолжаете выполнение программы.

Вы можете перенаправить ввод и/или вывод вашей программы, используя перенаправление оболочки с помощью команды run. Например,

run > outfile

запускает вашу программу, перенаправляя ее вывод в файл ./outfile.

Отладка уже запущенного процесса

attach process-id
Эта команда присоединяется к выполняющемуся процессу (process-id) - процессу, который был запущен вне GDB (команда info files показывает ваши активные целевые платформы). В качестве аргумента команда получает идентификатор процесса. Обычный способ узнать идентификатор процесса - воспользоваться утилитой pidin или командой отладчика info pidlist. Команда attach не повторяется, если вы нажмете Enter второй раз после выполнения команды.

Чтобы использовать attach вы также должны обладать полномочиями для посылки сигнала процессу.

Когда вы используете attach, вы должны сначала использовать команду file, чтобы указать программу, выполняемую в процессе, и загрузить ее таблицу символов.

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

detach
Когда вы закончили отлаживать присоединенный процесс, для его освобождения из под управления GDB вы можете использовать команду detach. Отсоединение процесса продолжает его выполнение. После команды detach, этот процесс и GDB снова становятся совершенно независимыми, и вы можете присоединить или запустить с помощью run другой процесс. Команда detach не повторяется, если вы нажмете Enter еще раз после выполнения команды.

Если вы выйдете из GDB или используете команду run, пока у вас есть присоединенный процесс, вы убьете этот процесс. По умолчанию, GDB запрашивает подтверждение, если вы пытаетесь сделать одну из этих вещей; вы можете контролировать, нужно вам это подтверждение или нет, используя команду set confirm.

Уничтожение отлаживаемого процесса

kill
Уничтожить отлаживаемый процесс (процесс в котором ваша программа выполняется под управлением GDB).

Эта команда полезна, если вы хотите отладить дамп памяти, а не выполняющийся процесс. GDB игнорирует любые дампы памяти, пока ваша программа выполняется.

Команда kill также полезна, если вы хотите перекомпилировать и перекомпоновать вашу программу. В ЗОСРВ «Нейтрино» можно изменять исполняемый файл во время его работы в процессе. Если вы хотите запустить новую версию, завершите текущий процесс ; в этом случае, когда вы в следующий раз введете run, GDB заметит, что файл изменился, и заново прочитает символьную таблицу (стараясь при этом сохранить ваши точки останова).

Отладка программ с несколькими потоками

В ЗОСРВ «Нейтрино» одна программа может иметь несколько потоков выполнения. Каждый поток имеет свои собственные регистры и стек выполнения, и, возможно, свои собственные участки памяти.

GDB предоставляет следующие возможности для отладки многопоточных программ:

Возможности отладки потоков GDB позволяют вам наблюдать все потоки во время выполнения вашей программы, но когда управление переходит к GDB, один конкретный поток выделяется для отладки. Он называется текущим потоком. Отладочные команды показывают информацию о программе с точки зрения текущего потока. Для отладочных целей, GDB присваивает свои собственные номера потоков, всегда в виде одного целого числа, каждому потоку в вашей программе.

info threads
Вывести краткую информацию обо всех имеющихся в данный момент в вашей программе потоках. Для каждого потока, GDB отображает (в этом порядке):
  1. Номер потока, назначенный GDB
  2. Идентификатор потока на целевой системе (systag)
  3. Краткие сведения о текущем кадре стека для этого потока
Звездочка (*) слева от номера потока GDB обозначает текущий поток. Например:
(gdb) info threads 3 process 35 thread 27 0x34e5 in sigpause () 2 process 35 thread 23 0x34e5 in sigpause () * 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8) at threadtest.c:68
thread threadno
Сделать поток с номером threadno текущим. Аргумент команды, threadno, является внутренним номером потока GDB, который показан в первом поле вывода команды info threads. GDB отвечает, выводя системный идентификатор выбранного вами потока, и обзор ее кадра стека:
(gdb) thread 2 [Switching to process 35 thread 23] 0x34e5 in sigpause ()
threads apply [threadno] [all] args
Команда thread apply позволяет вам применить команду к одному или нескольким потокам. Задайте номера потоков, на которые вы хотите воздействовать, в аргументе threadno. Чтобы применить команду ко всем потокам, используйте thread apply all args.

Когда GDB останавливает вашу программу, вследствие точки останова или по сигналу, он автоматически выбирает поток, в котором появилась точка останова или сигнал. GDB предупреждает вас о переключении контекста сообщением в форме [Switching to systag] для идентификации потока.

См. Остановка и запуск многопоточных программ, для дополнительной информации о поведении GDB, когда вы останавливаете и запускаете многопоточную программу.

См. Установка точек наблюдения, для информации о точках наблюдения в многопоточных программах.

Отладка программ с дочерними процессами

GDB не имеет специальных возможностей для отладки программ, создающих дополнительные процессы с помощью функции fork(). Когда программа вызывает fork(), GDB будет продолжать отладку родительского процесса, а дочерний процесс будет выполняться беспрепятственно. Если выполнение дочернего процесса дойдет до места, где вы установили точку останова, дочерний процесс получит сигнал SIGTRAP, который приведет к остановке процесса (если он не перехватывает этот сигнал).

Однако, если вы хотите отладить дочерний процесс, существует достаточно простое решение:

  1. Поместите вызов sleep() в код программы, который дочерний процесс выполнит после fork(). Может быть удобным вызывать sleep() только если установлена определенная переменная среды или если существует определенный файл, так что задержка не будет происходить, если вы не захотите отлаживать дочерний процесс.

  2. Пока дочерний процесс спит, используйте утилиту pidin (см. Справочник по утилитам) или GDB-команду info pidlist для получения ее идентификатора процесса.

  3. Затем укажите GDB (новому экземпляру GDB, если вы отлаживаете также и родительский процесс) присоединиться к дочернему процессу (см. Отладка уже запущенного процесса). Начиная с этого момента, вы можете отлаживать дочерний процесс точно также, как любой другой процесс, к которому вы присоединились.

Остановка и продолжение исполнения

Внутри GDB ваша программа может остановиться по нескольким причинам, таким как сигнал, точка останова, или достижение новой строки после команды GDB, такой как step. Затем вы можете просматривать и изменять значения переменных, устанавливать новые точки останова и удалять старые, и затем продолжить выполнение. Обычно, выводимые GDB сообщения предоставляют достаточную информацию о состоянии вашей программы, но вы также можете запросить эту информацию в любое время.

info program
Отобразить информацию о состоянии вашей программы: выполняется она или нет, каким процессом она является и почему остановлена.

Точки останова, точки наблюдения и исключения

Точка останова останавливает вашу программу всякий раз, когда ее выполнение достигает определенной точки. Для каждой точки останова вы можете добавлять условия для лучшего управления условиями остановки. Вы можете устанавливать точки останова командой break и ее вариантами (см. Установка точек останова), чтобы задать место, где должна остановиться ваша программа, по номеру строки, имени функции или точному адресу. В языках с обработкой исключений (таких как GNU C++), вы также можете установить точку останова там, где появляется исключение (см. Точки останова и исключения).

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

Вы можете установить, что значения из вашей программы должны отображаться автоматически, когда GDB останавливается на точке останова. см. Автоматическое отображение.

Когда вы создаете точку останова, наблюдения или перехвата, GDB присваивает ей номер; эти номера являются последовательными целыми числами, начинающимися с 1. Во многих командах для управления различными возможностями точек останова, вы используете эти номера для указания, какую точку останова вы хотите изменить. Каждая точка останова может быть включена или отключена; если точка останова отключена, она не оказывает никакого влияния на вашу программу, пока вы снова не включите ее.

Установка точек останова

Точки останова устанавливаются командой break (сокращенно b). Вспомогательная переменная отладчика $bpnum хранит номер последней установленной вами точки останова; см. Вспомогательные переменные, для обсуждения того, что вы можете делать со вспомогательными переменными.

Вы можете задавать место для установки новой точки останова несколькими способами:

break function
Установить точку останова на входе в функцию function. При использовании языков, допускающих перегрузку символов, таких как С++, function может ссылаться более чем на одно возможное место останова. См. Меню точки останова, для обсуждения такой ситуации.
break +offset
break -offset
Установить точку останова через несколько строк впереди или сзади от позиции, на которой выполнение остановилось в текущем выбранном кадре стека.
break linenum
Установить точку останова на строке linenum в текущем исходном файле. Текущий исходный файл - это файл, исходный текст которого отображался последним. Точка останова остановит вашу программу сразу перед выполнением какого-либо кода на этой строке.
break filename:linenum
Установить точку останова на строке linenum в исходном файле filename.
break filename:function
Установить точку останова на входе в функцию function, находящуюся в файле filename. Указание имени файла вместе с именем функции является излишним, за исключением ситуаций, когда несколько файлов содержат одинаково названные функции.
break *address
Установить точку останова по адресу address. Вы можете использовать это для установки точек останова в тех частях вашей программы, которые не имеют отладочной информации или исходных файлов.
break
При вызове без аргументов, break устанавливает точку останова на инструкции, которая должна быть выполнена следующей в выбранном кадре стека (см. Проверка стека). В любом выбранном кадре, кроме самого внутреннего, это останавливает вашу программу, как только управление возвращается в этот кадр. Это похоже на результат команды finish в кадре внутри выбранного кадра - за исключением того, что finish не оставляет активной точки останова. Если вы используете break без аргументов в самом внутреннем кадре, GDB останавливается, когда в следующий раз достигает текущего места; это может быть полезно внутри циклов.

Обычно GDB игнорирует точки останова, когда он возобновляет выполнение, пока не будет выполнена хотя бы одна инструкция. Если бы он этого не делал, вы не могли бы продолжать выполнение после точки останова, не отключив сперва эту точку останова. Это правило применяется вне зависимости от того, существовала или нет точка останова, когда ваша программа остановилась.
break ... if cond
Установить точку останова с условием cond; каждый раз, когда достигается точка останова, происходит вычисление выражения cond, и остановка происходит только если эта величина не равна нулю - то есть, если cond истинно. Троеточие (...) означает один из возможных аргументов, перечисленных выше (или отсутствие аргументов), описывающих место остановки. См. Условия останова, для большей информации об условных точках останова.

Существует несколько вариантов команды break, использующих тот же синтаксис, что и выше:

tbreak
Установить точку останова только до первой активизации. Точка останова устанавливается аналогичным образом, как и с помощью команды break, но она автоматически удаляется после того, как ваша программа первый раз на ней остановится. См. Отключение точек останова.
hbreak
Установить аппаратно-поддерживаемую точку останова. Точка останова устанавливается аналогичным образом, как и с помощью команды break, но она требует аппаратной поддержки (и некоторые целевые платформы могут ее не иметь).

Основной целью этого является отладка кода EPROM/ROM, так что вы можете установить точку останова на инструкции без изменения инструкции.
thbreak
Установить аппаратно-поддерживаемую точку останова, включенную только до первой активизации. Точка останова устанавливается аналогичным образом, как и с помощью команды break. Однако, как в случае команды tbreak, точка останова автоматически уничтожается после того, как программа первый раз на ней остановится. Также, как и в случае команды hbreak, точка останова требует аппаратной поддержки и некоторые целевые платформы могут ее не иметь. См. Отключение точек останова и Условия останова.
rbreak regex
Установить точки останова на всех функциях, удовлетворяющих регулярному выражению regex. Эта команда устанавливает безусловные точки останова при всех совпадениях, выводя список всех установленных точек останова. После установки, они рассматриваются точно так же, как точки останова, установленные командой break. Вы можете удалять их, отключать, или делать их условными таким же способом, как любые другие точки останова.

При отладке программ, написанных на С++, rbreak полезна для установки точек останова на перегруженных функциях, не являющихся членами никакого специального класса.

Следующие команды отображают информацию о точках останова и точках наблюдения:

info breakpoints [n]
info break [n]
info watchpoints [n]
Вывести таблицу всех установленных и не удаленных точек останова, наблюдения и перехвата, со следующими колонками для каждой точки: Если точка останова условная, info break показывает условие на строке, следующей за этой точкой; команды точки останова, если они есть, перечисляются после этого.

info break с номером точки останова n в качестве аргумента отображает только эту точку. Вспомогательная переменная $_ и адрес по умолчанию для просмотра для команды x устанавливаются равными адресу последней из перечисленных точек останова (см. Проверка памяти).

info break отображает то число раз, которое точка останова была активирована. Это особенно полезно при использовании вместе с командой ignore. Вы можете игнорировать большое число активаций точки останова, посмотреть информацию о точке останова чтобы узнать, сколько раз она активировалась, и затем запустить заново, игнорируя на единицу меньше, чем это число. Это быстро приведет вас к последней активации этой точки останова.

GDB позволяет вам установить любое число точек останова в одном и том же месте вашей программы. В этом нет ничего глупого или бессмысленного. Когда точки останова являются условными, это даже полезно (см. Условия останова).

GDB сам иногда устанавливает точки останова в вашей программе для специальных целей, таких как правильная обработка longjmp() (в программах на С). Этим внутренним точкам останова присваиваются отрицательные номера, начиная с -1; info breakpoints не отображает их.

Вы можете увидеть эти точки останова с помощью служебной команды GDB maint info breakpoints.

maint info breakpoints
Используя тот же формат, что и info breakpoints, отображает как точки останова, установленные вами явно, так и те, которые GDB использует для внутренних целей. Колонка типа определяет, какого типа точка останова показана:

Установка точек наблюдения

Вы можете использовать точку наблюдения для остановки выполнения, как только изменится значение какого-либо выражения, не предсказывая конкретное место, где это может произойти.

Хотя в настоящее время точки наблюдения выполняются на два порядка медленнее, чем точки останова, они могут помочь выявить ошибки в тех случаях, когда вы не знаете, в какой именно части вашей программы находится ошибка.

watch expr
Устанавливает точку наблюдения за выражением expr. GDB остановит программу, когда выраж сохраняется программой и его величина изменяется.
rwatch expr
Устанавливает точку наблюдения, которая остановит программу, когда наблюдаемое выражение expr считывается программой.
awatch expr
Устанавливает точку наблюдения, которая остановит программу, когда выражение expr либо считывается, либо сохраняется программой.
info watchpoints
Эта команда печатает список точек наблюдения, останова и перехвата; это то же самое, что и info break.


Note: В многопоточных программах точки наблюдения являются лишь частично полезными. С текущей реализацией точек наблюдения, GDB может наблюдать только за значением выражения в одном потоке. Если вы уверены, что выражение может измениться только вследствие действий внутри текущего потока (и если вы также уверены, что никакой другой поток не может стать текущим), то вы можете использовать точки наблюдения как обычно. Однако, GDB может не заметить, когда действия в не текущем потоке изменяют выражение.

Точки останова и исключения

Некоторые языки, например GNU C++, реализуют обработку исключений. Вы можете использовать GDB, чтобы узнать, что заставило вашу программу вызвать исключение, и перечислить исключения, которые ваша программа готова обработать в данный момент времени.

catch exceptions
Вы можете установить точки останова в активных обработчиках исключений с помощью команды catch. Аргумент exceptions - это список имен исключений, которые нужно перехватывать.

Вы можете использовать info cath, чтобы увидеть список активных обработчиков исключений. См. Информация о кадре.

В настоящее время существуют некоторые ограничения на обработку исключений в GDB:

Иногда catch - не лучший способ отладки обработки исключений: если вам нужно точно знать, где возникает исключение, лучше остановиться до вызова обработчика исключения, так как таким образом вы можете увидеть стек до того, как будет выполнено какое-либо разворачивание стека. Если вместо этого вы установите точку останова в обработчике исключений, может быть нелегко выяснить, где возникло исключение.

Чтобы остановиться непосредственно перед вызовом обработчика исключений, вам необходимо знать реализацию. В случае GNU C++ исключения вызываются вызовом библиотечной функции с именем __raise_exception(), которая имеет следующий интерфейс ANSI C:

void __raise_exception( void **addr, void *id );
/* addr - это адрес, где хранится идентификатор исключения.
id - идентификатор исключения. */

Чтобы отладчик перехватил все исключения до того, как произойдет разворачивание стека, установите точку останова на __raise_exception(). См. Точки останова, точки наблюдения и исключения.

С условной точкой останова (см. Условия останова), которая зависит от значения id, вы можете остановить свою программу при возникновении определенного исключения. Вы можете использовать несколько условных точек останова, чтобы остановить вашу программу при возникновении любого исключения.

Удаление точек останова

Часто бывает необходимо уничтожить точку останова или точку наблюдения, когда она сделала свое дело и вы больше не хотите останавливать там свою программу. Это называется удалением точки останова. Точка останова, которая была удалена, более не существует; она забыта.

С помощью команды clear вы можете удалять точки останова в соответствии с тем, где они находятся в вашей программе. С помощью команды delete вы можете удалять отдельные точки останова или точки наблюдения, указывая их номера.

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

clear
Удаляет любые точки останова, установленные на следующей инструкции, которая должна быть выполнена в выбранном кадре стека (см. Выбор кадра). Когда выбран самый внутренний кадр, это хороший способ удалить ту точку останова, на которой ваша программа только что остановилась.
clear function
clear filename:function
Удалить любые точки останова, установленные на входе в функцию function.
clear linenum
clear filename:linenum
Удалить все точки останова, установленные на или внутри кода на указанной строке linenum.
delete [breakpoints] [bnums...]
Удалить точки останова или точки наблюдения или из диапазона bnum, указанного в качестве аргумента. Если аргумент не задан, удалить все точки останова (GDB запрашивает подтверждение, если у вас не установлено set confirm off). Вы можете сократить это команду как d.

Отключение точек останова

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

Вы отключаете и включаете точки останова, и точки наблюдения командами enable и disable, возможно указывая один или более номеров точек останова в качестве аргументов. Используйте info break или info watch для вывода списка точек останова, и точек наблюдения, если вы не знаете какие номера использовать.

Точка останова или точка наблюдения может находиться в одном из четырех состояний:

Включена
Точка останова останавливает вашу программу. Точка останова, установленная командой break, изначально находится в таком состоянии.
Отключена
Точка останова не оказывает воздействия на вашу программу.
Включена до первого срабатывания
Точка останова останавливает вашу программу, но потом становится отключенной.
Включена для удаления
Точка останова останавливает вашу программу, но сразу после этого она удаляется навсегда.

Вы можете использовать следующие команды для включения или отключения точек останова, и точек наблюдения:

disable [breakpoints] [bnums...]
Отключить указанные в диапазоне bnums точки останова, или все точки останова, если ни одна не перечислена. Отключенная точка останова не оказывает никакого действия, но она не забывается. Все параметры, такие как счетчик игнорирований, условия и команды запоминаются, на случай, если точка останова позже будет снова включена. Вы можете сокращать disable как dis.
enable [breakpoints] [bnums...]
Включает указанные в диапазоне bnums (или все определенные) точки останова. Они снова становятся значимыми для остановки вашей программы.
enable [breakpoints] once bnums...
Временно включить указанные в диапазоне bnums точки останова. GDB отключает любую из этих точек останова немедленно после срабатывания.
enable [breakpoints] delete bnums...
Включить указанные в диапазоне bnums точки останова до первого срабатывания, затем удалить их. GDB удаляет любую из этих точек останова, как только ваша программа останавливается на ней.

Кроме точек останова, установленных командой tbreak (см Установка точек останова), установленные вами точки останова изначально включены; следовательно, они становятся отключенными или включенными только когда вы используете одну из вышеперечисленных команд. (Команда until может устанавливать и удалять свою собственную точку останова, но она не изменяет состояние ваших других точек останова; см. Продолжение и выполнение по шагам).

Условия останова

Простейшая точка останова останавливает вашу программу каждый раз, когда управление достигает заданного места. Вы можете также указать условие для точки останова. Условие является простым булевым выражением в вашем языке программирования (см. Выражения). Точка останова с условием вычисляет выражение каждый раз, когда ваша программа достигает ее, и ваша программа остановится только в том случае, если условие истинно.

Это противоположно использованию утверждений для проверки правильности программы; в этом случае, вы хотите остановиться, когда утверждение нарушается - то есть, когда условие ложно. В С, если вы хотите проверить утверждение, выраженное условием assert, вы должны установить условие !assert на соответствующей точке останова.

Условия также допускаются для точек наблюдения; вам они могут не понадобиться, так как точка наблюдения так или иначе контролирует значение выражения - но может оказаться проще, скажем, просто установить точку наблюдения на имя переменной и указать условие, проверяющее, является ли новое значение тем, которое нас интересует.

Условия останова могут иметь побочные эффекты, и даже могут вызывать функции в вашей программе. Это может быть полезным, например, для активации функций, которые запоминают продвижение выполнения вашей программы, или для использования ваших собственных функций вывода для форматирования специальных структур данных. Результаты полностью предсказуемы, если нет другой включенной точки останова по тому же адресу. (В этом случае, GDB может сначала увидеть другую точку останова и остановить вашу программу программу без проверки условия первой точки останова.) Заметьте, что команды точек останова обычно более удобны и гибки, чем условия останова, для выполнения побочных эффектов, когда достигается точка останова (см. Список команд точки останова).

Условия останова могут быть заданы в момент установки точки останова, используя if в аргументах команды break. См. Установка точек останова. Они могут быть также изменены в любой момент с помощью команды condition. Команда watch не распознает ключевое слово if; condition является единственным способом наложить дальнейшие условия на точку наблюдения.

condition bnum expression
Задайте выражение expression как условие остановки для точки останова или точки наблюдения с номером bnum. После того, как вы установили условие, данная точка останова с номером bnum остановит вашу программу только если значение выражения expression будет истинным (ненулевым, в С). Когда вы используете condition, GDB немедленно проверяет выражение expression на синтаксическую корректность и для определения, что символы в нем имеют объекты ссылки в контексте вашей точки останова. Однако, GDB в действительности не вычисляет выражение expression в момент подачи команды condition. см. Выражения.
condition bnum
Снимает условие с точки останова с номером bnum. Она становится обычной безусловной точкой останова.

Специальным случаем условия для точки останова является остановка только когда точка останова была достигнута определенное число раз. Это настолько полезно, что существует специальный способ сделать это, используя счетчик игнорирования точки останова. Каждая точка останова имеет счетчик игнорирования, являющийся целым числом. Как правило, счетчик игнорирования равен нулю, и, следовательно, не производит никакого действия. Но если ваша программа достигает точки останова, чей счетчик игнорирования положителен, тогда вместо того чтобы остановиться, она лишь уменьшит его на единицу и продолжит выполнение. В результате, если величина счетчика игнорирования равна n, точка останова не остановит программу следующие n раз, когда программа его достигнет.

ignore bnum count
Устанавливает счетчик игнорирований точки останова с номером bnum в значение count. Следующие count раз, когда точка останова будет достигнута, выполнение вашей программы не будет остановлено; кроме как уменьшения счетчика игнорирований, GDB не производит никаких действий.

Чтобы точка останова сработала при следующем достижении, установите счетчик в ноль.

Когда вы используете continue для возобновления выполнения вашей программы от точки останова, вы можете установить счетчик игнорирований непосредственно как аргумент к continue, а не использовать ignore. См. Продолжение и выполнение по шагам.

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

Вы можете достигнуть эффекта счетчика игнорирований с помощью такого условия, как $foo-- <= 0, используя вспомогательную переменную отладчика, которая уменьшается каждый раз. см. Вспомогательные переменные.

Список команд точки останова

Вы можете подать любой точке останова ( или точке наблюдения ) ряд команд, которые будут выполняться при остановке вашей программы на этой точке останова. Например, вы можете захотеть вывести значения определенных выражений, или включить другие точки останова.

commands [bnum]
... command-list ...
end
Определяет список команд command-list для точки останова с номером bnum. Сами команды указываются в следующих строках. Для завершения списка команд, введите строку, содержащую только end.

Чтобы удалить все команды от точки останова, введите commands и немедленно за этим end, то есть задайте пустой список команд.

Без аргумента bnum, commands относится к последней установленной точке останова или к точке наблюдения (но не к последней встреченной).

Нажатие Enter, как средство повторения последней команды GDB, отключено внутри command-list.

Вы можете использовать команды для точки останова, чтобы снова запустить вашу программу на выполнение. Просто используйте команду continue, или step, или любую другую команду, возобновляющую выполнение.

После команды, возобновляющей выполнение, любые другие команды в списке игнорируются. Так сделано потому, что каждый раз, когда вы возобновляете выполнение (даже просто с помощью next или step), вы можете встретить другую точку останова - которая может иметь свой собственный список команд, что приведет к неоднозначности, какой из списков выполнять.

Если в качестве первой команды в списке команд вы укажете silent, обычное сообщение об остановке на точке останова не будет выводиться. Это может быть желательно для точек останова, которые должны вывести определенное сообщение, и затем продолжить выполнение. Если никакая из оставшихся команд ничего не выводит, вы не увидите никакого знака о том, что точка останова была достигнута. silent имеет смысл только в начале списка команд точки останова.

Команды echo, output и printf позволяют вам более точно контролировать выводимый текст, и часто полезны в "тихих" точках останова.

Например, вот как вы можете использовать команды точки останова для вывода величины x на входе в foo(), когда x положительна:

break foo if x>0 commands silent printf "x is %d\n",x cont end

Одним из применений команд точки останова является компенсация одной ошибки, так, чтобы вы могли искать другую. Поместите точку останова сразу после строки кода, содержащей ошибку, задайте ей условие для определения случая, в котором было сделано что-то ошибочное, и определите команды для присвоения правильных значений тем переменным, для которых это требуется. Закончите командой continue, чтобы ваше программа не останавливалась, а начните с команды silent, чтобы не было никакого вывода. Вот пример:

break 403 commands silent set x = y + 4 cont end

Меню точки останова

Некоторые языки программирования (особенно С++) допускают, чтобы одно и то же имя функции было определено несколько раз, для применения в различных контекстах. Это называется перегрузкой. Когда имя функции перегружается, команды break function не достаточно, чтобы указать GDB, где вы хотите установить точку останова.

Если вы столкнулись с этой проблемой, вы можете использовать команду типа break function(types) для указания, какую конкретную версию функции вы имеете в виду. В противном случае, GDB предлагает вам выбор из пронумерованных вариантов для различных возможных точек останова, и ждет вашего выбора с выводом символа ">". Первыми двумя вариантами всегда являются "[0] cancel" и "[1] all". Ввод "1" устанавливает точку останова на каждом определении функции function, а ввод "0" прерывает команду break без установки новых точек останова.

Например, следующая выдержка из сеанса иллюстрирует попытку установить точку останова на перегруженной функции String::after(). Мы выбрали три конкретных определения имени функции:

(gdb) b String::after [0] cancel [1] all [2] file:String.cc; line number:867 [3] file:String.cc; line number:860 [4] file:String.cc; line number:875 [5] file:String.cc; line number:853 [6] file:String.cc; line number:846 [7] file:String.cc; line number:735 > 2 4 6 Breakpoint 1 at 0xb26c: file String.cc, line 867. Breakpoint 2 at 0xb344: file String.cc, line 875. Breakpoint 3 at 0xafcc: file String.cc, line 846. Multiple breakpoints were set. Use the "delete" command to delete unwanted breakpoints. (gdb)

Продолжение и выполнение по шагам

Продолжение означает возобновление выполнения программы до ее нормального завершения. А пошаговое выполнение означает выполнение еще одного "шага" (step) вашей программы, где "шаг" (step) может быть либо одной строкой исходного кода, либо одной машинной инструкцией (в зависимости от того, какую именно команду вы используете). И в случае продолжения, и в случае выполнения по шагам, ваша программа может остановиться и раньше, вследствие точки останова или сигнала. (Если она останавливается по сигналу, вы можете использовать handle, или signal 0 для возобновления выполнения. См. Сигналы).

continue [ignore_count]
c [ignore_count]
fg [ignore_count]
Возобновить выполнение программы, с того адреса, где ваша программа остановилась последний раз; все точки останова, установленные по этому адресу, пропускаются. Необязательный аргумент ignore_count позволяет вам задать количество последующих игнорирований точки останова в этом месте; его действие совпадает с действием ignore (см. Условия останова).

Аргумент ignore_count имеет смысл только если ваша программа остановилась в точке останова. В остальных случаях, аргумент к continue игнорируется.

Синонимы c и fg, предоставляются исключительно для удобства, и имеют в точности тот же смысл, что и continue.

Чтобы возобновить выполнение с другого места, вы можете использовать return (см. Возврат из функции) чтобы вернуться назад к вызывающей функции; или jump (см. Продолжение исполнения с другого адреса) для перехода к произвольному месту в вашей программе.

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

step
Продолжить выполнение вашей программы, пока управление не достигнет другой строки исходного текста, затем остановить ее и возвратить управление GDB. Эту команду можно сокращать до s.

Note: Если вы используете команду step, когда управление находится внутри функции, которая была скомпилирована без отладочной информации, выполнение продолжается, пока управление не достигнет функции, которая имеет ее. Аналогично, пошаговое выполнение не будет заходить в функцию, скомпилированную без отладочной информации. Для пошагового выполнения таких функций используйте команду stepi, описанную ниже.

Команда step останавливается только на первой инструкции строки исходного текста. Это предотвращает множественные остановки, которые в противном случае могут возникнуть в операторе switch, цикле for, и так далее. step продолжает останавливаться, если функция, имеющая отладочную информацию, вызывается внутри строки.

Также, команда step входит в функцию только если для нее существует информация о номерах строк. Иначе она действует как команда next. Это позволяет избежать проблем, появляющихся при использовании cc -gl на машинах MIPS.
step count
Продолжает выполнение как по команде step, но делает это число count раз. Если достигается точка останова, или приходит сигнал, не связанный с пошаговым выполнением, до выполнения числа шагов, пошаговое выполнение сразу останавливается.
next [count]
Продолжает выполнение до следующей строки исходного текста в текущем (внутреннем) кадре стека. Это аналогично step, но вызовы функций, которые появляются внутри строки кода, выполняются без остановки. Выполнение останавливается, когда управление достигает другой строки кода в исходном уровне стека, который выполнялся, когда вы дали команду next. Эта команда сокращается как n.

Аргумент count является счетчиком повторений, как для step.

Команда next останавливается только на первой инструкции исходной строки. Это предотвращает множественные остановки, которые иначе могут возникнуть в операторах switch, циклах for, и так далее.
finish
Продолжить выполнение до возврата из функции в выбранном кадре стека. Напечатать возвращенное значение (если таковое существует).

Сравните это с командой return (см. Возврат из функции).
u
until
Продолжить выполнение до достижения строки исходного текста, следующей за текущей, в текущем кадре стека. Эта команда используется для избежания выполнения цикла по шагам больше одного раза. Она похожа на команду next, за исключением того, что когда until встречает переход, она автоматически продолжает выполнение, пока счетчик выполнения программы не станет больше, чем адрес перехода.

Это означает, что когда вы достигаете конца цикла после его выполнения по шагам, until продолжает выполнение вашей программы, пока она не выйдет из цикла. Напротив, команда next в конце цикла просто переходит назад в начало цикла, что заставляет вас выполнять по шагам следующую итерацию.

until всегда останавливает вашу программу, если она пытается выйти из текущего кадра стека.

until может привести к несколько неожиданным результатам, если порядок машинных кодов не совпадает с порядком строк исходного текста. Например, в следующем отрывке сеанса отладки, команда f (frame) показывает, что выполнение остановилось на строке 206; хотя, когда мы используем until, мы переходим к строке 195:
(gdb) f #0 main (argc=4, argv=0xf7fffae8) at m4.c:206 206 expand_input(); (gdb) until 195 for ( ; argc > 0; NEXTARG) {

Это произошло потому, что для эффектвности выполнения компилятор сгенерировал код для проверки окончания цикла в конце, а не в начале цикла - даже если проверка в цикле for языка С написана до тела цикла. Кажется, что команда until переместилась назад к началу цикла, когда двигалась к этому выражению; однако, в действительности она не переходила к более раннему оператору - в отношении фактического машинного кода.

until без аргументов работает посредством пошагового выполнения отдельных инструкций, и, следовательно, является более медленной, чем until с аргументом.
until location
u location
Продолжить выполнение вашей программы, пока либо указанное место location не будет достигнуто, либо не произойдет возврат из текущего кадра стека. Аргумент location может быть любой из доступных форм аргумента для break (см. Установка точек останова). Эта форма команды использует точки останова, и, следовательно, является более быстрой, чем until без аргумента.
stepi [count]
si [count]
Выполнить одну машинную инструкцию, затем остановиться и вернуться в отладчик. При пошаговом выполнении машинных инструкций, часто бывает полезным сделать команду display/i $pc. Это заставляет GDB автоматически отображать инструкцию, которая будет выполняться следующей, каждый раз, когда ваша программа останавливается. см. Автоматическое отображение.

Аргумент count является счетчиком повторений, как для step.
nexti [count]
ni [count]
Выполнить одну машинную инструкцию, но если это вызов функции, продолжать до возврата из нее.

Аргумент count является счетчиком повторений, как для next.

Сигналы

Сигнал - это асинхронное событие, которое может произойти в программе. Операционная система определяет возможные типы сигналов и дает каждому типу имя и номер. В таблице ниже приведены некоторые примеры сигналов:

Таблица сигналов:

Сигнал Когда применятся
SIGINT Когда вы вводите знак прерывания, Ctrl - C
SIGSEGV Когда программа ссылается на область памяти, отличную от всех используемых областей.
SIGALARM При срабатывании интервального таймера (возникает только, если ваша программа запросила временной сигнал).

Некоторые сигналы, такие как SIGALRM, являются обычной частью функционирования вашей программы. Другие, такие как SIGSEGV, обозначают ошибки; эти сигналы являются фатальными (они немедленно убивают вашу программу), если программа не определила заранее другой способ их обработки. SIGINT не указывает на ошибку в вашей программе, но обычно является фатальным, так что он может выполнять функцию прерывания: убить программу.

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

Обычно, GDB установлен так, чтобы:

Вы можете изменить эти установки командой handle.

info signals
info handle
Вывести таблицу всех типов сигналов и описания, как GDB будет обрабатывать каждый из них. Вы можете использовать эту команду, чтобы посмотреть номера всех определенных типов сигналов.
handle signal keywords...
Изменить способ, которым GDB обрабатывает сигнал signal. Аргумент signal может быть номером сигнала или его именем (с SIG или без него в начале). Аргумент keywords определяет, какие сделать изменения.

Ключевые слова, допускаемые командой handle, могут быть сокращены. Вот их полные имена:

nostop
GDB не должен останавливать вашу программу при получении этого сигнала. Но он все еще может вывести сообщение, уведомляющее о получении сигнала.
stop
GDB должен остановить вашу программу при получении этого сигнала. Это также подразумевается под ключевым словом print.
print
GDB должен вывести сообщение при возникновении данного сигнала.
noprint
GDB вообще не должен замечать возникновение сигнала. Это также подразумевается под ключевым словом nostop.
pass
GDB должен позволить вашей программе увидеть этот сигнал; ваша программа может обработать сигнал, или же она может завершиться, если сигнал фатальный и не обработан.
nopass
GDB не должен позволять вашей программе видеть этот сигнал.

Когда сигнал останавливает вашу программу, он невидим для нее, пока вы не продолжите выполнение. Затем ваша программа видит сигнал, если в данный момент на рассматриваемый сигнал распространяется действие команды pass. Другими словами, после того, как GDB сообщит о сигнале, вы можете использовать команду handle c pass или nopass, чтобы указать, должна ли ваша программа увидеть этот сигнал при продолжении.

Вы также можете использовать команду signal для того, чтобы помешать вашей программе увидеть сигнал или, наоборот, заставить ее заметить обычно игнорируемый сигнал, или чтобы подать ей произвольный сигнал в любое время. Например, если ваша программа остановилась вследствие какой-либо ошибки обращения к памяти, вы можете сохранить правильные значения в ошибочные переменные и продолжить выполнение, в надежде посмотреть на дальнейшее выполнение, но ваша программа вероятно немедленно остановилась бы из-за фатального сигнала, как только она бы его заметила. Чтобы помешать этому, вы можете продолжить выполнение с "signal 0". См. Подача сигнала вашей программе.

Остановка и запуск многопоточных программ

Когда ваша программа имеет несколько потоков выполнения (см. Отладка программ с несколькими потоками), вы можете выбрать, установить точки останова либо во всех, либо в каких-то отдельных потоках.

break linespec thread threadno
break linespec thread threadno if ...
Аргумент linespec определяет строки исходного текста; существует несколько способов их задания, но результат всегда один и тот же - указание на строку исходного текста.

Используйте классификатор thread threadno с командой точки останова, чтобы указать GDB, что вы хотите остановить программу, только когда определенный поток достигнет этой точки. Аргумент threadno - это один из числовых идентификаторов потока, присвоенный GDB, показываемый в первой колонке при выводе info threads.

Если при установке точки останова вы не укажете thread threadno, точка останова будет действовать для всех потоков вашей программы.

Вы также можете использовать классификатор thread для условных точек останова; в этом случае, поместите thread threadno перед условием точки останова, вот так:
(gdb) break frik.c:13 thread 28 if bartab > lim

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

Наоборот, когда вы снова запускаете программу, все потоки начинают выполняться. Это верно даже при пошаговом выполнении такими командами, как step или next.

В частности, GDB не может пошагово выполнять все потоки параллельно. Так как планированием выполнения потока занимается микроядро Нейтрино (не контролируется GDB), то пока в текущем потоке выполняется один шаг, в других может выполниться несколько. Более того, когда выполнение программы останавливается, другие потоки вообще могут остановиться в середине операторов, а не на границе между ними.

Вы даже можете обнаружить, что после продолжения исполнения или после пошагового выполнения ваша программа остановилась в другом потоке. Это случается всякий раз, когда другой поток достигает точки останова, получает сигнал или в нем возникает исключение, прежде чем перваый поток завершает выполнение того, что вы запросили.

Проверка стека

Когда ваша программа остановилась, первое, что вам нужно знать - где она остановилась и как она туда попала.

Каждый раз, когда ваша программа производит вызов функции, о нем создается определенная информация. Она включает положение вызова в вашей программе, параметры вызова и локальные переменные вызываемой функции. Информация сохраняется в блоке данных, называемом кадром стека. Кадры стека размещаются в области памяти, называемой стеком вызовов.

Команды GDB для проверки стека позволяют вам увидеть всю эту информацию при остановке вашей программы.

Один из кадров стека является выбранным GDB, и многие команды GDB неявно относятся к нему. В частности, когда вы запрашиваете у GDB значение переменной вашей программы, это значение находится в выбранном кадре. Для выбора интересующего вас кадра существуют специальные команды GDB. См Выбор кадра.

Когда ваша программа останавливается, GDB автоматически выбирает текущий выполняющийся кадр и выдает его краткое описание, аналогично команде frame (см. Информация о кадре).

Кадры стека

Cтек вызовов разделен на непрерывные участки, называемые кадрами стека, или кадрами для краткости; каждый кадр является данными, связанными с одним вызовом одной функции. Кадр содержит аргументы, переданные функции, ее локальные переменные и адрес, с которого она выполняется.

Когда ваша программа стартует, стек содержит только один кадр - для функции main(). Он называется начальным или внешним кадром. Каждый раз при вызове функции создается новый кадр. При каждом выходе из функции, кадр этого вызова функции уничтожается. Если функция является рекурсивной, для нее может существовать множество кадров. Кадр для функции, исполняемой в данный момент, называется внутренним кадром. Это кадр, созданный самым последним из всех существующих кадров стека.

Внутри вашей программы кадры стека идентифицируются своим адресом. Кадр стека состоит из множества байт, каждый из которых имеет свой собственный адрес; каждый тип компьютеров имеет свой способ для выбора одного байта, чей адрес служит адресом кадра. Обычно, пока выполнение происходит в данном кадре, этот адрес содержится в регистре, называемом регистром указателя кадра.

GDB присваивает номера всем существующим кадрам стека, начиная с "0" для внутреннего кадра, "1" для вызвавшего его кадра, и так далее. В действительности, эти номера не существуют в вашей программе; они назначаются GDB, чтобы предоставить вам способ различать кадры стека в командах GDB.

Некоторые компиляторы позволяют компилировать функции так, чтобы они выполнялись без создания кадров стека. (Например, опция gcc -fomit-frame-pointer создает функции без кадра.) Это иногда делается с часто используемыми библиотечными функциями, чтобы сохранить время, требуемое для установки кадра. GDB имеет ограниченные возможности для обработки таких функциональных вызовов. Если вызов внутренней функции происходит без создания кадра стека, GDB, тем не менее, описывает его так, как если бы он имел отдельный кадр, который имеет, как обычно, номер "0", позволяя корректно трассировать цепочку функциональных вызовов. Однако, GDB не имеет средств для работы с функциями без кадра в другом месте стека.

frame args
Команда frame позволяет вам перемещаться от одного кадра стека к другому, и выводить выбранный вами кадр. Аргумент args может быть либо адресом кадра, либо его номером. Без аргумента, frame выводит текущий кадр стека.
select-frame
Команда select-frame позволяет вам перемещаться от одного кадра стека к другому без его вывода. Это "тихая" версия frame.

Цепочки вызовов

Цепочка вызовов предоставляет собой информацию о том, как ваша программа оказалась там, где она есть. Она отображает по одной строке для каждого кадра, начиная с текущего выполняющегося кадра (кадра "0"), за которым следует кадр, из которого он был вызван (кадр "1"), и далее вверх по стеку.

backtrace
bt
Вывести цепочку вызовов всего стека: по одной строке на кадр, для всех кадров в стеке.

Вы можете прервать цепочку вызовов в любое время, введя знак системного прерывания, обычно Ctrl - C.
backtrace n
bt n
То же самое, но выводятся только n внутренних кадров.
backtrace -n
bt -n
То же самое, но выводятся только n внешних кадров.

where и info stack (сокращенно info s) - дополнительные синонимы для backtrace.

Каждая строка в цепочке вызовов показывает номер кадра и имя функции. Счетчик команд также показывается, если только вы не используете set print address off. Цепочка вызовов также показывает имя исходного файла, номер строки и аргументы функции. Значение счетчика команд опускается, если он указывает на начало кода для данной строки.

Ниже приведен пример цепочки вызовов. Она была получена командой bt 3, так что она показывает три внутренних кадра:

#0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8) at builtin.c:993 #1 0x6e38 in expand_macro (sym=0x2b600) at macro.c:242 #2 0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08) at macro.c:71 (More stack frames follow...)

Информация о кадре с номером "0" не начинается со значения счетчика команд, что указывает на то, что ваша программа остановилась в начале кода для строки "993" файла builtin.c.

Выбор кадра

Большинство команд для проверки стека и других данных в вашей программе применяются к выбранному в данный момент кадру. Здесь приведены команды для выбора кадра стека; все они завершаются выводом краткого описания выбранного кадра стека.

frame n
f n
Выбрать кадр с номером n. Напоминаем, что кадр с номером "0" - это внутренний (исполняемый в данный момент) кадр, кадр с номером "1" - тот, из которого вызван нулевой, и так далее. Кадр с наибольшим номером - это кадр для функции main().
frame addr
f addr
Выбрать кадр, расположенный по адресу addr. В основном это полезно, если формирование цепочки кадров стека было нарушено из-за ошибки, сделавшей невозможным для GDB правильное присвоение номеров всем кадрам. Кроме того, это может быть полезным, когда у вашей программы есть несколько стеков и происходит переключение от одного к другому. В архитектуре MIPS команде frame для выбора произвольного кадра необходимо указать два адреса: указатель вершины стека и указатель команд.
up n
Переместиться вверх по стеку на n кадров. Для положительных значений n, это перемещение происходит по направлению к внешнему кадру, к кадрам с большими номерами, к кадрам, которые существуют дольше. По умолчанию n принимается равным "1".
down n
Передвинуться вниз по стеку на n кадров. Для положительных значений n, это продвижение происходит по направлению к внутреннему кадру, к кадру с меньшим номером, к кадрам, которые были созданы позже. По умолчанию, значение n принимается равным "1". Вы можете сокращать down как do.

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

Например:

(gdb) up #1 0x22f0 in main (argc=1, argv=0xf7fffbf4, env=0xf7fffbfc) at env.c:10 10 read_input_file (argv[i]);

После такого вывода, команда list без аргументов выводит десять строк, расположенных вокруг точки выполнения в кадре. См. Вывод строк исходного текста.

up-silently n
down-silently n
Эти две команды являются вариантами up и down соответственно, отличаясь от них тем, что делают свою работу "тихо", не отображая новый кадр. Они предназначены для использования в основном в командных сценариях GDB, где вывод может быть ненужным и отвлекающим.

Информация о кадре

Существует несколько других команд для вывода информации о выбранном кадре стека:

frame
f
При использовании без аргументов, эта команда не выбирает новый кадр, а выводит краткое описание текущего выбранного кадра стека. Эту команду можно сокращать как f. С аргументом, эта команда используется для выбора кадра стека. См. Выбор кадра.
info frame
info f
Эта команда выводит подробное описание выбранного кадра стека, включающее: Подробное описание полезно, если из-за какой-либо ошибки формат стека не соответствует обычному поведению.
info frame addr
info f addr
Вывести подробное описание кадра стека, расположенного по адресу addr, не выбирая этот кадр. Выбранный кадр этой командой не изменяется. Она требует параметр адрес того же типа, что и команда frame (для некоторых архитектур не один, а несколько). См. Выбор кадра.
info args
Вывести аргументы выбранного кадра, каждый на отдельной строке.
info locals
Вывести локальные переменные выбранного кадра, каждую на отдельной строке. Выводятся все переменные (объявленные как статические или как автоматические), доступные в точке выполнения выбранного кадра стека.
info catch
Выводит список всех обработчиков исключений, являющихся активными в текущей точке выполнения текущего кадра стека. Чтобы увидеть другие обработчики исключений, перейдите в соответствующий кадр (используя команды up, down или frame); затем наберите info catch. См. Точки останова и исключения.

MIPS-машины и стек функции

Компьютеры на базе MIPS используют необычный кадр стека, что иногда требует от GDB поиска в обратном направлении в объектном коде для нахождения начала функции.

Чтобы улучшить время отклика - особенно для встроенных приложений, где GDB может быть ограничен одной медленной последовательной строкой для этого поиска - вы можете ограничить предел этого поиска, используя одну из этих команд:

set heuristic-fence-post limit
Ограничить GDB предельным количеством байт limit на поиск начала функции. Значение "0" (по умолчанию) означает, что предельного значения байт нет. Однако, за исключением 0, чем больше предел, тем больше байт должна просмотреть функция heuristic-fence-post во время поиска и, следовательно, тем больше времени требуется для выполнения команды.
show heuristic-fence-post
Показать заданный предел поиска.

Эти команды доступны только в том случае, если GDB настроен для отладки программ на процессорах MIPS.

Проверка файлов с исходными текстами

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

Вывод строк исходного текста

Чтобы вывести строки файла с исходным текстом, используйте команду list (сокращенно l). По умолчанию выводятся десять строк. Существует несколько способов определения того, какую часть файла вы хотите вывести.

Здесь представлены наиболее часто используемые формы команды list:

list linenum
Вывести строки, расположенные вокруг строки с номером linenum в текущем исходном файле.
list function
Вывести строки, расположенные вокруг начала функции function.
list
Вывести еще определенное количество строк. Если последние выведенные строки выводились с помощью команды list, то выводятся строки, следующие за последними выведенными; если, однако, последней выведенной строкой была одиночная строка, выведенная как часть отображения кадра стека (см. Проверка стека), то выводятся строки, расположенные вокруг нее.
list -
Вывести строки, расположенные непосредственно перед последними выведенными.

По умолчанию, для любой из этих форм команды list GDB выводит десять строк исходного текста. Вы можете изменить это командой set listsize:

set listsize count
Установить количество count выводимых командой list строк в число (если аргумент команды list не задает явно какое-нибудь другое число).
show listsize
Отобразить количество строк, выводимых по команде list.

Повторение команды list нажатием Enter отбрасывает аргумент, так что это эквивалентно вводу просто list. Это полезнее, чем вывод тех же самых строк снова. Исключение сделано для параметра "-"; этот параметр сохраняется при повторе команды, так что каждое повторение приводит к перемещению вверх по исходному файлу.

Обычно команда list ожидает от вас ноль, один или два указателя строк linespec. Указатели строк linespec определяют строки исходного текста; существует несколько способов их задания, но результат всегда заключается в задании строки исходного текста. Вот полное описание возможных параметров команды list:

list linespec
Вывести строки, расположенные вокруг строки, определяемой linespec.
list first,last
Вывести строки с first до last. Оба параметра являются указателями строк.
list ,last
Вывести строки, расположенные перед last.
list first,
Вывести строки, начиная с first.
list +
Вывести строки, расположенные сразу за последними выведенными.
list -
Вывести строки, расположенные непосредственно перед последними выведенными.
list
Описано в предыдущем блоке.

Ниже перечислены способы указания одиночной строки исходного текста - все виды указателей строк (linespec).

number
Определяет строку с номером number из текущего исходного файла. Если в качестве параметров к команде list задано два указателя строк, это относится к тому же исходному файлу, что и первый указатель строки linespec.
+offset
Указывает на строку, смещенную вперед на смещение строк offset относительно последней выведенной строки. Когда используется в качестве второго указателя строки для команды list, имеющей два указателя, задает строку, смещенную на смещение строк offset вниз относительно строки, определенной первым указателем.
-offset
Указывает на строку, расположенную на смещение строк offset раньше последней выведенной строки.
filename:number
Задает строку номер number из исходного файла filename.
function
Определяет строку, с которой начинается тело функции function. Например, в языке С это строка с открывающейся фигурной скобкой.
filename:function
Определяет строку с открывающейся фигурной скобкой, с которой начинается тело функции function в файле filename. Имя файла необходимо лишь для того, чтобы избежать неоднозначности, когда в различных исходных файлах есть одинаково названные функции.
*address
Определяет строку, соответствующую адресу address программы. адрес может быть любым выражением.

Поиск в исходных файлах

Существуют две команды для поиска по регулярному выражению в текущем исходном файле.

forward-search regexp
search regexp
fo regexp
Команда forward-search regexp проверяет на соответствие регулярному выражению regexp каждую строку, начиная со строки, следующей за последней выведенной. Найденная строка выводится.
reverse-search regexp
rev regexp
Команда reverse-search regexp, двигаясь назад, проверяет на соответствие регулярному выражению regexp каждую строку, начиная с предшествующей последней выведенной. Найденная строка выводится.

Определение каталогов с исходными файлами

Исполняемые программы иногда не сохраняют имена каталогов, в которых находились исходные файлы, из которых они скомпилированы, а хранят лишь имена файлов. Даже если они их сохранили, каталоги могли быть перемещены в период между компиляцией и сеансом отладки. У GDB есть список каталогов для поиска исходных файлов; он называется путь для исходных файлов. Каждый раз, когда GDB требуется исходный файл, он перебирает по порядку все каталоги из этого списка, пока не находит файл с требуемым именем.


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

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

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

Когда вы запускаете GDB, путь для исходных файлов пуст. Для добавления каталогов, используйте команду directory.

directory dirname ...
dir dirname ...
Добавить каталог dirname в начало пути для исходных файлов. Этой команде могут быть заданы несколько имен, разделенные двоеточием (:) или пробелом (). Вы можете указать каталог, который уже содержится в пути для исходных файлов; это переместит его в начало, так что GDB будет просматривать его раньше.

Вы можете использовать строку $cdir для ссылки на каталог компиляции (если информация о нем сохранена), и $cwd для ссылки на текущий рабочий каталог. $cwd не есть то же самое, что ".". Первая отслеживает текущий рабочий каталог, который может меняться во время вашего сеанса работы с GDB, тогда как вторая сразу преобразовывается в текущий каталог в момент его добавления в путь для исходных файлов.
directory
Очистить путь для файлов с исходными текстами. Эта команда требует подтверждения.
show directories
Вывести путь поиска исходных файлов: показать, какие каталоги он содержит.

Если ваш путь для исходных файлов перемешан с уже неиспользуемыми каталогами, GDB может иногда вызвать недоумение, найдя неправильный вариант исходного файла. Вы можете исправить ситуацию следующим образом:

  1. Использовать directory без параметров, чтобы очистить путь поиска исходных файлов.

  2. Использовать directory с подходящими аргументами, чтобы переустановить каталоги, которые вы хотите видеть в пути для исходных файлов. Вы можете добавить все каталоги одной командой.

Исходный текст и машинный код

Вы можете использовать команду info line, чтобы отобразить cтроки исходного текста в программные адреса (и наоборот), и команду disassemble, чтобы вывести диапазон адресов в виде машинных инструкций. При запуске в режиме GNU Emacs, команда info line выводит стрелку, указывающую на заданную строку. Также info line выводит адреса как в символьной форме, так и в шестнадцатеричной.

info line linespec
Выводит начальный и конечный адреса скомпилированного кода, соответствующего строке исходного текста linespec. Вы можете определить строки исходного текста любым способом, воспринимаемым командой list (см. Вывод строк исходного текста).

Например, мы можем использовать info line для определения положения объектного кода первой строки функции m4_changequote:

(gdb) info line m4_changequote Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350.

Мы также можем запросить (используя *адрес как форму задания linespec), какая строка исходного текста соответствует определенному адресу:

(gdb) info line *0x63ff Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404.

После info line, адрес, используемый по умолчанию для команды x, меняется на начальный адрес строки, так что x/i достаточно для начала проверки машинного кода (см. Проверка памяти). Этот адрес также сохраняется как значение вспомогательной переменной $_ (см. Вспомогательные переменные).

disassemble
Эта специализированная команда служит для дампа диапазона памяти в виде машинных инструкций. Диапазоном памяти по умолчанию является функция, в которой находится счетчик программы в выбранном кадре. Одиночным аргументом этой команды является значение счетчика программы; GDB выводит дамп функции, которой принадлежит указанный адрес. Два аргумента определяют диапазон адресов для дампа (первый включается, второй исключается).

Мы можем использовать disassemble для проверки диапазона объектного кода, показанного в последнем примере info line (в этом примере показаны машинные инструкции SPARC):

(gdb) disas 0x63e4 0x6404 Dump of assembler code from 0x63e4 to 0x6404: 0x63e4 <builtin_init+5340>: ble 0x63f8 <builtin_init+5360> 0x63e8 <builtin_init+5344>: sethi %hi(0x4c00), %o0 0x63ec <builtin_init+5348>: ld [%i1+4], %o0 0x63f0 <builtin_init+5352>: b 0x63fc <builtin_init+5364> 0x63f4 <builtin_init+5356>: ld [%o0+4], %o0 0x63f8 <builtin_init+5360>: or %o0, 0x1a4, %o0 0x63fc <builtin_init+5364>: call 0x9288 <path_search> 0x6400 <builtin_init+5368>: nop End of assembler dump.

set assembly-language instruction-set
Выбрать набор инструкций instruction-set для использования при дизассемблировании программы командами disassemble и x/i. Эта команда может быть полезной для архитектур, у которых есть более одного собственного набора инструкций.

В настоящее время, эта команда определена только для семейства Intel x86. Вы можете установить набор-инструкций instruction-set в режим i386 или i8086. По умолчанию установлен режим i386.

Разделяемые библиотеки

Вы можете использовать следующие команды для работы с разделяемыми библиотеками:

sharedlibrary [regexp]
Загружает символы разделяемой библиотеки для файлов, соответствующих заданному регулярному выражению regexp. Если регулярное выражение опущено, GDB пытается загрузить символы для всех загруженных разделяемых библиотек.
info sharedlibrary
Отображает состояние загруженных разделяемых библиотек.

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

set solib-search-path dir[:dir...]
Задает путь dir поиска для загрузки файлов символов разделяемой библиотеки, у которых нет абсолютного пути. Этот путь переопределяет переменные окружения PATH и LD_LIBRARY_PATH.
set solib-absolute-prefix prefix
Устанавливает префикс prefix для загрузки файлов символов абсолютной разделяемой библиотеки.
set auto-solib-add value
Делает загрузку символов разделяемой библиотеки автоматической или ручной с помощью значения аргумента value:

Вы можете запросить настройки этих параметров с помощью команд show solib-search-path, show solib-absolute-prefix и show auto-solib-add.

Проверка данных

Для проверки данных в вашей программе обычно используется команда print (сокращенно p) или ее синоним inspect. Она вычисляет и выводит значение выражения, записанного на том же языке, что и ваша программа.

print exp
print /f exp
exp является выражением (на языке исходного текста программы). По умолчанию, значение exp выводится в формате, соответствующем его типу данных; вы можете выбрать другой формат, указав "/f", где f - буква, определяющая формат; см. Форматы вывода.
print
print /f
Если вы опустите exp, GDB отображает последнее значение снова (из истории значений; см. История значений). Это предоставляет вам удобный способ изучить то же самое значение в другом формате.

Команда x позволяет проверять данные на более низком уровне. Она исследует данные в памяти по указанному адресу и выводит их в указанном формате. см. Проверка памяти.

Если вас интересует информация о типах или о том, как объявлены поля структуры или класса, используйте команду ptype exp вместо print. См. Проверка символьной таблицы.

Выражения

print и многие другие команды GDB допускают в качестве параметра выражение и вычисляют его значение. В выражении GDB допустимо использование любого типа констант, переменных или операторов, определенных в используемом вами языке программирования, включая условные выражения, вызовы функций, приведение типов и строковые постоянные. К сожалению, исключением являются символы, определенные командами препроцессора #define.

GDB поддерживает константы-массивы в выражениях, введенных пользователем. Синтаксис следующий: {элемент, элемент...}. Например, вы можете использовать команду print {1, 2, 3}, чтобы создать в памяти массив, который будет доступен в программе так же, как выделенный функцией malloc().

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

Приведения типов поддерживается во всех языках, а не только в С, так как бывает очень полезно преобразовать число в указатель, чтобы проверить структуру, расположенную по этому адресу в памяти.

GDB поддерживает эти операторы, в дополнении к следующим, являющимися общими для языков программирования:

@
"@" является бинарным оператором, позволяющим рассматривать области памяти как массивы. См. Искусственные массивы, для дополнительной информации.
::
"::" позволяет вам указывать переменную в терминах файла или функции, где она определена. См. Переменные программы.
{тип} адрес
Ссылается на объект типа тип, хранящийся в памяти по адресу адрес. Адрес может быть любым выражением, значением которого является целое число или указатель (но вокруг бинарных операторов, также как и вокруг оператора приведения типа, требуются скобки). Эта конструкция допустима, независимо от того, какого типа данные предположительно расположены по адресу.

Переменные программы

Чаще всего в качестве выражения используется имя переменной вашей программы.

Переменные в выражениях трактуются в контексте выбранного кадра стека (см. Выбор кадра); они могут быть:

Это означает, что в функции:

foo( a )
int a;
{
bar( a );
{
int b = test();
bar( b );
}
}

вы можете проверять и использовать переменную a всякий раз, когда ваша программа выполняется в пределах функции foo(), но вы можете использовать или проверять переменную b только тогда, когда ваша программа выполняется внутри блока, в котором она объявлена.

Есть исключение: вы можете ссылаться на переменную или функцию, областью видимости которой является единственный исходный файл, даже если точка текущего выполнения в нем не находится. Допускается существование нескольких переменных или функций с одинаковым именем (в различных исходных файлах). Если это так, обращение к этому имени приводит к непредсказуемым результатам. Если хотите, вы можете указать статическую переменную в конкретной функции или в файле, используя двойное двоеточие:

file::variable function::variable

Здесь файл file или функция function – название контекста для статической переменной variable. В первом случае вы можете использовать кавычки, чтобы GDB рассматривал имя файла как одно слово; например, чтобы вывести глобальное значение переменной x, определенной в f2.c:

(gdb) p 'f2.c'::x

Такое использование :: крайне редко конфликтует с похожим использованием той же записи в С++. GDB также поддерживает использование оператора определения области видимости С++ в выражениях.


Note: В некоторых случаях, в определенной точке функции (сразу после входа в новую область видимости, и непосредственно перед выходом из нее) может показаться, что локальная переменная имеет неверное значение.

Вы можете столкнуться с этой проблемой при пошаговом выполнении по одной машинной инструкции. Она возникает из-за того, что на большинстве машин процедура установки кадра стека (включая определения локальных переменных) занимает более одной инструкции; если вы производите пошаговое выполнение по одной машинной инструкции, может показаться, что переменная имеет неверное значение, пока кадр стека не будет полностью построен. При выходе, для уничтожения кадра стека обычно также требуется более одной инструкции; после начала пошагового выполнения этой группы инструкций, определения локальных переменных могут пропасть.


Искусственные массивы

Часто бывает полезным вывести несколько объектов одного типа, расположенных в памяти последовательно; часть массива или динамический массив, для которого в программе существует только указатель.

Вы можете это сделать, обращаясь к непрерывному участку памяти как к искусственному массиву, используя бинарный оператор @. Левым операндом для @ должен быть первый элемент желаемого массива, и он должен быть индивидуальным объектом. Правым операндом должна быть длина массива. Результатом операции будет массив, все элементы которого имеют тот же тип, что и левый аргумент. Первым элементом массива является левый операнд; второй элемент формируется из байт памяти, непосредственно следующих за байтами, содержащими первый элемент, и так далее. Например, если в программе есть строка:

int *array = (int *) malloc (len * sizeof (int));

то вы можете вывести содержимое array с помощью:

p *array@len

Левый операнд операции @ должен находиться в памяти. Значения массивов, полученных операцией @, при индескации ведут себя точно так же, как и другие массивы, и приводятся к указателям при использовании в выражениях. Искусственные массивы чаще всего появляются в выражениях через историю значений (см. История значений), после вывода одного из них.

Другой способ создания искусственного массива - использование приведения типов. Оно заново интерпретирует значение так, как если бы оно было массивом. Значение не обязано находиться в памяти:

(gdb) p/x (short[2])0x12345678 $1 = {0x1234, 0x5678}

Если вы опускаете длину массива (как в (type[])value), GDB для удобства вычисляет его размер для заполнения значениями как sizeof( value ) / sizeof( type ). Например:

(gdb) p/x (short[])0x12345678 $2 = {0x1234, 0x5678}

Иногда механизма искусственных массивов бывает недостаточно; в сравнительно сложных структурах данных, интересующие нас элементы могут не быть смежными - например, если вас интересуют значения указателей в массиве. Одно из полезных решений этой проблемы - использование вспомогательной переменной (см. Вспомогательные переменные) в качестве счетчика в выражении, выводящем первое интересующее нас значение, а затем повторять это выражение нажатием Enter. Предположим, например, у вас есть массив dtab указателей на структуры, и вас интересуют значения полей fv в каждой структуре. Ниже приведен пример ваших возможных действий:

set $i = 0 p dtab[$i++]->fv Enter Enter ...

Форматы вывода

По умолчанию, GDB печатает значение в соответствии с его типом. Это не всегда отвечает вашему желанию. Например, вы можете захотеть вывести число в шестнадцатеричной записи, или указатель в десятичной. Или вы можете захотеть просмотреть данные по некоторому адресу в памяти в виде строки символов или в виде инструкций. Для этого, при выводе значения укажите формат вывода.

Простейшим применением форматов вывода является форматирование вывода уже вычисленного выражения. Это осуществляется путем начала параметров команды print с косой черты и символа формата. Поддерживаются следующие символы формата:

x
Рассматривать биты значения как целое, и вывести целое в шестнадцатеричном виде.
d
Вывести как десятичное целое со знаком.
u
Вывести как десятичное целое без знака.
o
Вывести как восьмеричное целое.
t
Вывести как целое в двоичном виде. Буква "t" означает "two" (два). (Буква "b" не может использоваться, потому что этот символ формата также используются с командой x, где "b" означает байт. См. Проверка памяти).
a
Вывести в виде адреса, как абсолютного в шестнадцатеричной записи, так и в виде смещения от ближайшего предшествующего символа. Вы можете использовать этот формат для того, чтобы определить, где (в какой функции) расположен какой-либо неизвестный адрес:
(gdb) p/a 0x54320 $3 = 0x54320 <_initialize_vx+396>
c
Рассматривать как целое и вывести в виде строковой постоянной.
f
Рассматривать биты значения как число с плавающей точкой и вывести с использованием обычного синтаксиса для чисел с плавающей точкой.

Например, чтобы вывести счетчик программы в шестнадцатеричном виде (см. Регистры), введите:

p/x $pc


Note: Обратите внимание, что перед косой чертой не требуется пробела, потому что имена команд в GDB не могут содержать косую черту.

Чтобы вывести последнее значение из истории значений в другом формате, вы можете воспользоваться командой print только с указанием формата и без выражения. Например, p/x выведет последнее значение в шестнадцатеричной форме.

Проверка памяти

Вы можете использовать команду x (от слова examine) для проверки памяти в одном из нескольких форматов, независимо от типов данных вашей программы.

x/nfu addr
x addr
x
Для проверки памяти используйте команду x.

n, f и u - необязательные параметры, определяющие, сколько памяти отобразить и в каком формате; addr - это выражение, задающее адрес, с которого вы хотите начать отображение памяти. Если вы используете значения по умолчанию для nfu, то вам не нужно вводить косую черту "/". Некоторые команды устанавливают удобные значения по умолчанию для адреса addr.

n
Счетчик повторений, является десятичным целым числом; по умолчанию 1. Он определяет, сколько памяти отобразить (считая в единицах u).
f
Формат отображения - это один из форматов, используемых командой print:
s
строка, оканчивающаяся нулем
i
машинная инструкция
x (первоначальное значение по умолчанию)
шестнадцатеричная форма

Значение по умолчанию изменяется каждый раз, когда вы используете либо x, либо print.
u
Размер единицы измерений, может иметь одно из этих значений:
b
байты
h
полуслова (два байта)
w (первоначальное значение по умолчанию)
слова (четыре байта)
g
длинные слова (восемь байт)

Каждый раз, когда вы определяете размер единицы измерений командой x, этот размер становится размером по умолчанию при последующем использовании x. (Для форматов s и i, размер единицы измерений игнорируется и обычно не пишется.)
addr
Адрес, с которого вы хотите, чтобы GDB начинал отображение памяти. Значение выражения не обязано должно быть указателем (хотя может им быть); оно всегда интерпретируется как целый адрес байта в памяти. См. Выражения, для дополнительной информации о выражениях. Значением по умолчанию для addr обычно является адрес, следующий за последним изученным адресом, но некоторые другие команды также могут устанавливать значение по умолчанию: info breakpoints (в адрес последней выведенной точки останова), info line (в начальный адрес строки) и print (если вы используете эту команду для отображения значения из памяти).

Например, x/3uh 0x54320 - запрос на вывод трех полуслов (h) памяти в формате беззнаковых десятичных целых (u), начиная с адреса 0x54320. x/4xw $sp выводит четыре слова (w) памяти, расположенные над указателем стека (здесь "$sp"; см. Регистры), в шестнадцатеричном виде (x).

Так как все буквы, обозначающие размер единиц измерения, отличаются от букв, определяющих форматы вывода, вы не должны запоминать, формат или размер единиц измерений указывается раньше; это можно делать в любом порядке. Спецификации вывода "4xw" и "4wx" означают в точности одно и то же. (Однако, число n должно быть первым; "wx4" не сработает).

Хотя размер единицы измерения u игнорируется для форматов s и i, тем не менее вы можете воспользоваться счетчиком повторений n; например, 3i указывает, что вы хотите вывести три машинные инструкции, включая любые операнды. Команда disassemble предоставляет альтернативный способ просмотра машинных инструкций; см. Исходный текст и машинный код.

Все значения по умолчанию для аргументов команды x разработаны таким образом, чтобы облегчить продолжение сканирования памяти с минимальными конкретизациями при очередном использовании x. Например, после того, как вы просмотрели три машинные инструкции с помощью x/3i addr, вы можете просмотреть следующие семь, используя просто x/7. Если вы повторяете команду x нажатием Enter, число повторений n остается прежним; другие аргументы берутся по умолчанию, как для последовательных использований x.

Адреса и их содержимое, выводимые командой x, не сохраняются в истории значений, так как они мешали бы. Вместо этого, GDB делает их доступными для последующего использования в выражениях как значения вспомогательных переменных $_ и $__. После команды x, последний проверенный адрес доступен для использования в выражениях в вспомогательной переменной $_. Содержимое этого адреса, проверенного только что, доступно во вспомогательной переменной $__.

Если команде x задан счетчик повторений, адрес и его содержимое сохраняются из последнего выведенного элемента памяти; это не то же самое, что последний выведенный адрес, если в последней строке вывода были отображены несколько элементов.

Автоматическое отображение

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

2: foo = 38 3: bar[5] = (struct hack *) 0x3804

Это отображение показывает номера элементов, выражения и их текущие значения. Как и при отображении, запрашиваемом вручную с помощью x или print, вы можете указать предпочитаемый формат вывода; фактически, display определяет, следует использовать print или x, в зависимости от того, на сколько жесткая ваша спецификация формата: используется x, если вы указываете размер элемента или один из двух форматов (i и s), которые поддерживаются только x; в остальных случаях используется print.

display exp
Добавляет выражение exp к списку выражений, отображаемых каждый раз, когда ваша программа останавливается. См. Выражения. display не повторяется, если вы повторно нажимаете Enter после ее использования.
display/frmt exp
Если frmt определяет только формат вывода, а не размер или счетчик повторений, выражение exp добавляется в список автоматического отображения, но его отображение осуществляется в указанном формате frmt. см. Форматы вывода.
display/frmt addr
Если форматом является i или s, или он включает в себя размер элементов или их число, выражение addr добавляется как адрес памяти для проверки при каждой остановке вашей программы. Под проверкой в данном случае подразумевается выполнение x/frmt addr. см. Проверка памяти.

Например, команда display/i $pc может быть полезна, чтобы при каждой остановке видеть машинную инструкцию, которая будет выполняться следующей ($pc - это общее обозначение счетчика программы; см. Регистры).

undisplay dnums...
delete display dnums...
Удалить элементы с номерами dnums из списка выражений, подлежащих отображению. undisplay не повторяется при последующем нажатии Enter. (Иначе вы сразу получили бы сообщение об ошибке "No display number ...").
disable display dnums...
Отключить отображение элементов с номерами dnums. Отключенные элементы не выводятся автоматически, но и не забываются. Впоследствии их можно снова включить.
enable display dnums...
Включить отображение элементов с номерами dnums. Выражения, соответствующие этим номерам, снова будут выводиться автоматически, пока вы укажете обратное.
display
Отобразить текущие значения выражений из списка, точно так же, как это происходит при остановке вашей программы.
info display
Вывести список выражений, ранее установленных для автоматического отображения, каждое с его номером элемента, но не показывая значений. Список включает отключенные выражения, с соответствующей пометкой. Он также включает в себя выражения, которые не могут быть показаны прямо сейчас, потому что обращаются к автоматическим переменным, недоступным в данный момент.

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

Например, если вы дадите команду display last_char, находясь внутри функции с аргументом last_char, GDB будет отображать этот аргумент, пока программа останавливается внутри этой функции. Как только она остановится где-то еще - где нет переменной last_char - отображение будет отключено автоматически. Вы можете снова включить его при следующей остановке программы там, где last_char будет вновь иметь смысл.

Параметры вывода

GDB предоставляет следующие способы управления выводом массивов, структур и символов.

Данные параметры полезны при отладке программ на любом языке:

set print address
set print address on
GDB выводит адреса памяти, показывающие положение стека, структур, указателей, точек останова, и так далее, даже когда он отображает также содержимое этих адресов. Значение по умолчанию установлено в on. Например, вот как выглядит отображение кадра стека с установленным set print address on:
(gdb) f #0 set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>") at input.c:530 530 if (lquote != def_lquote)
set print address off
Не выводить адреса при отображении их содержимого. Вот, например, тот же кадр стека, отображенный с установкой set print address off:
(gdb) set print addr off (gdb) f #0 set_quotes (lq="<<", rq=">>") at input.c:530 530 if (lquote != def_lquote)

Вы можете использовать set print address off, чтобы удалить все машинно-зависимые отображения из интерфейса GDB. Например, с print address off, вы должны получить одинаковый текст для цепочек вызовов на всех машинах, независимо от того, включают они указатели в качестве аргументов или нет.
show print address
Показать, должны выводиться адреса или нет.

При выводе адреса в символьной форме, GDB обычно выводит ближайший предшествующий символ плюс смещение. Если этот символ не определяет адрес однозначно (например, это имя, областью действия которого является один исходный файл), вам может потребоваться дать пояснения. Один из способов это сделать - с помощью info line; например, info line *0x4537. Альтернативный способ заключается в том, чтобы GDB выводил имя исходного файла и номер строки при выводе символьного адреса:

set print symbol-filename on
Заставляет GDB выводить имя исходного файла и номер строки символа в символьной форме адреса.
set print symbol-filename off
Не выводить имя исходного файла и номер строки символа. Принимается по умолчанию.
show print symbol-filename
Показать, будет ли GDB выводить имя исходного файла и номер строки в символьной форме адреса или нет.

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

Вы также можете захотеть видеть символьную форму только в том случае, если выводимый адрес достаточно близок к ближайшему предшествующему символу:

set print max-symbolic-offset max-offset
Заставляет GDB выводить символьные формы только тех адресов, для которых смещение между ближайшим предшествующим символом и адресом меньше, чем максимальное смещение max-offset. По умолчанию значение max-offset равно 0; в этом случае GDB всегда выводит адрес в символьной форме, если ему предшествует хоть какой-нибудь символ.
show print max-symbolic-offset
Запрашивает информацию о максимальном смещении, для которого GDB выводит символьную форму адреса.

Если у вас есть указатель, и вы не знаете, на что он указывает, попробуйте использовать команду set print symbol-filename on. Затем вы можете определить название и исходный файл переменной, на которую он указывает, используя p/a указатель. Это интерпретирует адрес в символьной форме. Например, здесь GDB показывает, что переменная ptt указывает на другую переменную t, определенную в файле hi2.c:

(gdb) set print symbol-filename on (gdb) p/a ptt $4 = 0xe008 <t in hi2.c>


Note: Для указателей, указывающих на локальные переменные, p/a не показывает символьное имя и имя файла, которому принадлежит объект ссылки, даже если установлена соответствующая опция set print.

Другие установки управляют выводом объектов различных типов:

set print array
set print array on
Структурный вывод массивов. Этот формат удобенее для чтения, но занимает больше места. По умолчанию отключено.
set print array off
Вернуться к сжатому формату вывода массивов.
show print array
Показать, какой формат (сжатый или структурный) выбран для отображения массивов.
set print elements number-of-elements
Установить ограничение на количество выводимых GDB элементов массива (number-of-elements). Если GDB выводит большой массив, вывод прерывается после того, как будет выведено установленное командой set print elements. Это ограничение также действует при отображении строк. Установка число-элементов в ноль означает, что вывод не ограничен.
show print elements
Показать количество элементов большого массива, которые будут выведены GDB. Если это число равно 0, вывод не ограничивается.
set print null-stop
Указывает GDB прекращать вывод символов массива, как только встретится первый NULL. Это полезно, когда большие массивы фактически содержат только короткие строки.
set print pretty on
Указывает GDB выводить структуры в формате с отступами, по одному элементу в строке, например:
$1 = { next = 0x0, flags = { sweet = 1, sour = 1 }, meat = 0x54 "Pork" }
set print pretty off
Указывает GDB выводить структуры в компактном формате, как здесь:
$1 = {next = 0x0, flags = {sweet = 1, sour = 1}, \ meat = 0x54 "Pork"}

Этот формат устанавливается по умолчанию.
show print pretty
Показать, какой формат GDB использует для вывода структур.
set print sevenbit-strings on
Осуществлять вывод, используя только семибитные символы; если этот параметр установлен, GDB отображает любые восьмибитные символы (в строках или символьных значениях), используя запись "\nnn". Эта установка очень удобна, если вы работаете на английском (ASCII) и используете старший бит символов как маркер или "мета"-бит.
set print sevenbit-strings off
Выводить восьмибитные символы полностью. Это позволяет использовать большее количество международных наборов символов, и устанавливается по умолчанию.
show print sevenbit-strings
Показать, выводит GDB только семибитные литеры или нет.
set print union on
Указывает GDB выводить объединения, содержащиеся в структурах. Устанавливается по умолчанию.
set print union off
Указывает GDB не выводить объединения, содержащиеся в структурах.
show print union
Показать, будет ли GDB выводить объединения, содержащиеся в структурах. Например, пусть даны описания:

typedef enum {Tree, Bug} Species;
typedef enum {Big_tree, Acorn, Seedling} Tree_forms;
typedef enum {Caterpillar, Cocoon, Butterfly} Bug_forms;
struct thing {
Species it;
union {
Tree_forms tree;
Bug_forms bug;
} form;
};
struct thing foo = {Tree, {Acorn}};

с установленным set print union on, команда p foo выведет:
$1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}

а с установленным set print union off, эта же команда выведет:
$1 = {it = Tree, form = {...}}

Следующие установки представляют интерес при отладке программ на С++:

set print demangle
set print demangle on
Печатать идентификаторы С++ в их изначальной, а не в закодированной ("искаженной") форме, передаваемой ассемблеру и компоновщику для сборки с контролем типа. Установлено по умолчанию.
show print demangle
Показать, в какой форме (искаженной или восстановленной) выводятся идентификаторы С++.
set print asm-demangle
set print asm-demangle on
Выводить идентификаторы С++ в их исходной форме, а не в искаженной, даже при выводе ассемблерного кода, например при дизассемблировании инструкций. По умолчанию отключено.
show print asm-demangle
Показать, в какой форме (закодированной или восстановленной) выводятся имена С++ при выводе кода ассемблера.
set demangle-style style
Выбрать одну из нескольких схем кодирования, используемых различными компиляторами для представления имен С++. Аргумент style может быть следующим:
auto
Позволить GDB выбрать стиль декодирования посредством изучения вашей программы.
gnu
Декодирование основывается на алгоритме кодирования компилятора GNU С++ ( g++). Устанавливается по умолчанию.
lucid
Декодирование основывается на алгоритме кодирования компилятора Lucid С++ (lcc).
arm
Декодировать, используя алгоритм из "C++ Annotated Reference Manual". Одной этой установки недостаточно, чтобы производить отладку исполняемых программ, сгенерированных cfront. Чтобы реализовать это, GDB требует дальнейших усовершенствований.
foo
Показать список форматов.
show demangle-style
Отобразить текущий стиль кодирования, используемый для декодирования символов С++.
set print object
set print object on
При отображении указателя на объект, идентифицировать фактический (производный), а не объявленный тип объекта, используя таблицу виртуальных функций.
set print object off
Отображать только объявленный тип объекта, не ссылаясь на таблицу виртуальных функций. Устанавливается по умолчанию.
show print object
Показать, какой из типов объекта (фактический или объявленный) выводится.
set print static-members
set print static-members on
Выводить статические переменные-члены при отображении объекта С++. Установлено по умолчанию.
set print static-members off
Не выводить статические переменные-члены при отображении объекта С++.
show print static-members
Показать, выводятся статические переменные-члены С++ или нет.
set print vtbl
set print vtbl on
Осуществлять структурный вывод таблиц виртуальных функций С++. По умолчанию отключено.
set print vtbl off
Не производить структурного вывода таблиц виртуальных функций С++.
show print vtbl
Показать, производится структурный вывод таблиц виртуальных функций С++ или нет.

История значений

Значения, выведенные командой print, сохраняются в истории значений GDB. Это позволяет вам обращаться к ним в других выражениях. Значения сохраняются, пока таблица символов не будет заново считана или уничтожена (например, командами file или symbol-file). При изменении таблицы символов, история значений уничтожается, так как значения могут содержать указатели на типы, определенные в таблице символов.

Выведенным значениям присваиваются номера в истории, по которым вы можете на них ссылаться. Эти номера являются последовательными целыми числами, начинающимися с 1. Команда print показывает номер в истории, присвоенный значению, выводя перед ним $num = , где num - это номер в истории.

Для обращения к какому-либо предшествующему значению, используйте $, за которым следует номер в истории. Способ, которым print маркирует вывод продуман так, чтобы напоминать вам об этом. Просто $ ссылается на самое последнее значение в истории, а $$ - на предпоследнее. $$n ссылается на n-е с конца значение; $$2 - значение, находящееся перед $$, $$1 эквивалентно $$, а $$0 эквивалентно $.

Предположим, например, вы только что вывели указатель на структуру и хотите посмотреть ее содержимое. Для этого достаточно ввести:

p *$

Если у вас есть цепочка структур, где компонента next указывает на следующую структуру, вы можете вывести содержимое следующей структуры так:

p *$.next

Вы можете выводить последовательные звенья в цепочке повторяя эту команду. Это можно сделать простым нажатием Enter.


Note: В историю записываются значения, а не выражения. Если значение x равно 4, и вы наберете:

print x set x=5

то значение, записанное в историю значений командой print, будет по-прежнему равно 4, хотя значение x изменилось.


show values
Вывести из истории последние десять значений, с их номерами. Это похоже на команду p $$9, повторенную десять раз, за исключением того, что show values не изменяет историю.
show values n
Вывести десять значений из истории, расположенных вокруг элемента с номером n.
show values +
Вывести десять значений из истории, следующих сразу после последнего выведенного значения. Если доступных значений больше нет, show values + не выводит ничего.

Нажатие Enter для повтора show values n действует точно так же, как show values +.

Вспомогательные переменные

GDB предоставляет вспомогательные переменные, которые вы можете в нем использовать, чтобы сохранить значение и обратиться к нему позже. Эти переменные существуют только в GDB; они не являются частью вашей программы и установка вспомогательной переменной не оказывает непосредственного влияния на ее дальшейшее выполнение. Поэтому вы можете пользоваться ими совершенно свободно.

Имена вспомогательных переменных начинаются с $. Любое имя с приставкой $ может использоваться для вспомогательной переменной, если только оно не является предопределенным машинно-зависимым именем регистра, (см. Регистры). Ссылки на историю значений, напротив, есть числа, которым предшествует $. см. История значений.

Вы можете сохранить значение во вспомогательной переменной с помощью выражения присваивания, как если бы вы устанавливали переменную в вашей программе. Например:

set $foo = *object_ptr

сохранит в $foo значение объекта, на который указывает object_ptr.

Первое использование вспомогательной переменной создает ее, но значением переменной будет void, пока вы не присвоите ей новое. С помощью другого присваивания вы можете в любое время изменить значение.

Вспомогательные переменные не имеют фиксированного типа. Вы можете присваивать вспомогательной переменной значение любого типа, включая структуры и массивы, даже если у этой переменной уже было значение другого типа. Будучи использованной в выражении, вспомогательная переменная имеет тип своего текущего значения.

show convenience
Вывести список используемых вспомогательных переменных с их значениями. Сокращается как show con.

Один из способов использования вспомогательных переменных - в качестве увеличивающегося счетчика или продвигающегося указателя. Например, чтобы напечатать поле из последовательных элементов массива структур:

set $i = 0 print bar[$i++]->contents

Повторяйте эту команду нажатием Enter.

Некоторые вспомогательные переменные создаются GDB автоматически, и им присваиваются значения, которые вероятно могут оказаться полезными.

$_
Переменная $_ устанавливается автоматически командой x в последний проверенный адрес (см. Проверка памяти). Другие команды, которые устанавливают адрес по умолчанию для проверки командой x, также присваивают $_ упомянутый адрес; эти команды включают info line и info breakpoint. Переменная $_ имеет тип void *, если только она не установлена командой x; в этом случае она является указателем на тип переменной $__.
$__
Переменная $__ устанавливается автоматически командой x в значение, находящееся по последнему проверенному адресу. Ее тип выбирается соответствующим формату, в котором это значение было выведено.
$_exitcode
Переменной $_exitcode автоматически присваивается код завершения, когда отлаживаемая программа завершается.

Регистры

В выражениях, вы можете обращаться к содержимому машинных регистров, обозначая их как переменные с именами, начинающимися с $. Имена регистров различаются от машины к машине; для вывода имен регистров, используемых на вашей машине, воспользуйтесь командой info registers.

info registers
Вывести имена и содержимое всех регистров, кроме регистров с плавающей точкой (в выбранном кадре стека).
info all-registers
Вывести имена и содержимое всех регистров, включая регистры с плавающей точкой.
info registers regname ...
Выводит относительное значение каждого из указанных в regname регистров. Как подробно обсуждается ниже, значения регистров обычно относятся к выбранному кадру стека. Аргумент regname может быть любым допустимым на вашей машине именем регистра, с $ в начале имени или без.

GDB распознает четыре "стандартных" имени регистров, которые доступны (в выражениях) на большинстве машин - если только они не конфликтуют с каноническими для архитектуры мнемониками регистров:

$pc
Счетчик программы.
$sp
Указатель вершины стека.
$fp
Регистр, содержащий указатель на текущий кадр стека.
$ps
Регистр, содержащий состояние процессора.

Например, вы можете вывести счетчик программы в шестнадцатеричной записи с помощью:

p/x $pc

или вывести следующую исполняемую инструкцию, используя:

x/i $pc

или увеличить указатель вершины стека на четыре с помощью:

set $sp += 4


Note: Это способ удаления одного слова из стека на машинах, где стеки растут по убыванию в памяти (большинство современных машин). Это предполагает, что выбран самый внутренний кадр стека; установка $sp недопустима, когда выбраны другие кадры стека. Чтобы удалить целые кадры из стека, независимо от архитектуры машины, используйте клавишу Enter.

Когда возможно, эти четыре стандартных имени регистров доступны на вашей машине, даже если она имеет другие канонические мнемоники, если не возникает конфликта. Команда info registers выводит канонические имена.

Когда регистр проверяется таким образом, GDB всегда рассматривает содержимое обычного регистра как целое. Некоторые машины имеют специальные регистры, которые могут содержать только значение с плавающей точкой; их значения трактуются как величины с плавающей точкой. Не существует способа сослаться на содержимое обычного регистра как на величину с плавающей точкой (хотя вы можете вывести его значение командой print как величину с плавающей точкой, используя print/f $regname).

Некоторые регистры имеют различные "необработанные" и "виртуальные" форматы данных. Это означает, что формат данных, в котором операционная система сохраняет содержимое регистра, не совпадает с тем, который обычно воспринимается вашей программой. Например, регистры сопроцессора с плавающей точкой 68881 всегда сохраняются в "расширенном" (необработанном) формате, но все программы на С работают с "двойным" (виртуальным) форматом. В подобных случаях, GDB обычно работает только с виртуальным форматом (форматом, имеющим смысл в вашей программе), но команда info registers выводит данные в обоих форматах.

Обычно значения регистров относятся к выбранному кадру стека (см. Выбор кадра). Это значит, что вы получаете значение, которое содержалось бы в регистре, если бы произошел выход из всех внутренних кадров стека и их сохраненные регистры были бы восстановлены. Для того чтобы увидеть истинное содержимое аппаратных регистров, вы должны выбрать самый внутренний кадр (с помощью "frame 0").

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

Аппаратные средства поддержки вычислений с плавающей точкой

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

info float
Отобразить аппаратно-зависимую информацию о модуле поддержки вычислений с плавающей точкой. Ее точное содержание и размещение зависит от микросхемы поддержки вычислений с плавающей точкой. В настоящее время, info float поддерживается на машинах с архитектурой x86.

Проверка символьной таблицы

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

Иногда вам может потребоваться сослаться на символы, содержащие необычные знаки, которые GDB обычно трактует как разделители слов. Наиболее часто это встречается при ссылках на статические переменные в других исходных файлах (см. Переменные программы). Имена файлов записаны в объектных файлах как отладочные символы, но GDB обычно производит разбор типичного имени файла, например foo.c, как три слова: "foo", ".", "c". Чтобы GDB идентифицировал foo.c как одно слово, заключите его в одинарные кавычки; например:

p 'foo.c'::x

ищет значение x в области видимости файла foo.c.

info address symbol
Описывает, где хранятся данные для символа symbol. Для регистровой переменной сообщается, в каком регистре она содержится. Для нерегистровой локальной переменной выводится смещение в кадре стека, по которому переменная всегда хранится.

Заметьте отличие от команды print &symbol, которая вообще не работает для регистровых переменных, а для локальной переменной из стека выводит точный адрес текущего экземпляра переменной.
whatis exp
Напечатать тип данных выражения exp. На самом деле выражение exp не вычисляется, а присутствующие в нем побочные операции (такие как присваивания или вызовы функций) не выполняются. См. Выражения.
whatis
Вывести тип данных $, последней записи в истории значений.
ptype typename
Вывести описание типа данных typename. Тип данных typename может быть именем типа или, для кода С, может иметь форму:
ptype exp
ptype
Вывести описание типа выражения exp. ptype отличается от whatis тем, что выводится детальное описание, а не только имя типа. Например, для такого описания переменной:

struct complex {double real; double imag;} v;

эти две команды выведут следущее:
(gdb) whatis v type = struct complex (gdb) ptype v type = struct complex { double real; double imag; }
Как и whatis, использование ptype без параметра относится к типу $, последней записи в истории значений.

info types regexp
info types
Вывести краткое описание всех типов, имена которых соответствуют регулярному выражению regexp (или всех типов вашей программы, если вы используете эту команду без параметра). Каждое полное имя типа сопоставляется так, как если бы оно было полной строкой; таким образом, i type value выдает информацию обо всех типах в вашей программе, чьи имена включают стpоку value, а i type ^value$ выдает инфоpмацию только о типах с полным именем value.

Эта команда отличается от ptype следующим: во-пеpвых, как и whatis, она не выводит детального описания; во-вторых, она перечисляет все исходные файлы, где определен тип.
info source
Показать имя текущего исходного файла - то есть исходного файла для функции, содержащей текущую точку выполнения, и язык, на котоpом она написана.
info sources
Вывести имена всех исходных файлов вашей программы, для которых имеется отладочная инфоpмация, организуя их в два списка: файлы с уже прочитанными символами, и файлы, символы которых будут пpочитаны, когда потребуется.
info functions
Вывести имена и типы данных всех опpеделенных функций.
info functions regexp
Вывести имена и типы данных всех опpеделенных функций, чьи имена удовлетворяют регулярному выражению regexp. Так, info fun step находит все функции, имена которых содержат step; info fun ^step находит функции с именами, начинающимися со step.
info variables
Напечатать имена и типы данных всех пеpеменных, объявленных вне функций (то есть исключая локальные пеpеменные).
info variables regexp
Вывести имена и типы данных всех пеpеменных (кpоме локальных), имена которых удовлетворяют регулярному выражению regexp.

Некоторые системы допускают замещение отдельных объектных файлов, составляющих вашу программу, без ее остановки и перезапуска. Если вы работаете в одной из таких систем, вы можете позволить GDB перезагрузить символы для автоматически пересобранных модулей:
maint print symbols filename
maint print psymbols filename
maint print msymbols filename
Записать дамп данных отладочных символов в файл filename. Эти команды используются для отладки кода GDB, осуществляющего чтение символов. Включаются только символы с отладочными данными.

Изменение исполнения

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

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

Присваивание значений пеpеменным

Для изменения значения переменной, вычислите выражение присваивания. См. Выражения. Например,

print x=4

сохраняет значение "4" в переменной x и затем выводит значение данного выражения (которое равно "4").

Если вы не хотите видеть значение присваивания, используйте команду set вместо print. Команда set аналогична команде print за исключением того, что значение выражения не выводится и не заносится в историю значений (см. История значений). Выражение вычисляется только ради его действия.

Если начало строки параметров команды set выглядит идентично подкоманде set, используйте вместо нее команду set variable. Эта команда аналогична set, но не имеет подкоманд. Например, если в вашей программе есть переменная width, то вы получите ошибку, если попытаетесь установить новое значение просто с помощью set width=13, потому что GDB имеет команду set width:

(gdb) whatis width type = double (gdb) p width $4 = 13 (gdb) set width=47 Invalid syntax in expression.

Недопустимое выражение, это, конечно, "=47". Для того чтобы действительно установить переменную программы width, используйте

(gdb) set var width=47

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

Для сохранения значений в произвольных местах памяти, используйте конструкцию "{...}" для создания значения определенного типа по определенному адресу памяти (см. Выражения). Например, {int}0x83040 ссылается на ячейку памяти 0x83040 как на целое (что предполагает соответствующий размер и представление в памяти), и:

set {int}0x83040 = 4

записывает в эту ячейку памяти значение "4".

Продолжение исполнения с другого адреса

Обычно, когда вы продолжаете выполнение программы, вы делаете это с того места, где она остановилась, командой continue. Вместо этого, вы можете продолжить выполнение с любого выбранного адреса при помощи следующих команд:

jump linespec
Возобновить выполнение со строки linespec. Если там есть точка останова, выполнение немедленно прекращается. См. Вывод строк исходного текста, для описания различных форм linespec.

Команда jump не изменяет ни текущий кадр стека, ни указатель стека, ни содержимое каких-либо ячеек памяти или регистров, кроме счетчика программы. Если строка linespec находится вне выполняющейся в настоящее время функции, результаты могут быть странными, если эти функции используют аргументы или локальные переменные разных типов. По этой причине, команда jump запрашивает подтверждение, если указанная строка не находится в функции, выполняющейся в настоящее время. Однако, даже странные результаты предсказуемы, если вы хорошо знакомы с машинным кодом вашей программы.
jump *address
Возобновить выполнение с инструкции, находящейся по адресу *address.

На многих системах, вы можете достичь такого же результата, как и с командой jump, сохранением нового значения в регистр $pc. Отличие заключается в том, что это не начинает выполнение вашей программы, а лишь изменяет адрес, с которого будет выполняться программа, когда вы продолжите выполнение. Например:

set $pc = 0x485

выполняет следующую команду continue или команду пошагового выполнения с адреса 0x485, а не с того адреса, где ваша программа остановилась. См. Продолжение и выполнение по шагам.

Наиболее общий случай использования команды jump состоит в возврате к выполнению части программы, возможно с большим количеством установленных точек останова, которая уже выполнилась, для того чтобы исследовать выполнение более детально.

Подача сигнала вашей программе

signal signal
Возобновить выполнение с места остановки вашей программы, но немедленно подать ей сигнал signal. Аргумент signal может быть именем или номером сигнала. Например, во многих системах signal 2 и signal SIGINT - два способа подать сигнал прерывания.

Наоборот, если сигнал signal является нулем, выполнение продолжается без подачи сигнала. Это полезно, если ваша программа остановилась из-за сигнала и в обычном случае увидит его при возобновлении выполнения командой continue; signal 0 продолжит выполнение без сигнала.

Команда signal не повторяется, когда вы нажимаете Enter второй раз после выполнения команды.

Вызов команды signal отличается от вызова утилиты kill из оболочки. Подача сигнала посредством kill заставляет GDB решать, что делать с сигналом, в зависимости от таблиц обработки сигналов (см. Сигналы). Команда signal передает сигнал непосредственно вашей программе.

Возврат из функции

return
return expression
Вы можете отменить выполнение вызова функции с помощью команды return. Если вы задаете параметр expression, его значение используется в качестве возвращаемого значения.

Когда вы используете return, GDB уничтожает выбранный кадр стека (и все кадры внутри него). Вы можете считать это преждевременным возвратом из уничтоженного кадра. Если вы хотите указать возвращаемое значение, задайте его в качестве аргумента к return.

Это выталкивает выбранный кадр стека (см. Выбор кадра) и все другие кадры внутри него, оставляя самым внутренним кадр, из которого произошел вызов. Этот кадр становится выбранным. Указанное значение сохраняется в регистрах, используемых для возвращаемых функцией значений.

Команда return не возобновляет выполнение; она оставляет программу остановленной в том состоянии, в котором бы она была сразу после возврата из функции. Напротив, команда finish (см. Продолжение и выполнение по шагам) возобновляет выполнение до естественного возврата из выбранного кадра стека.

Вызов функций программы

call expr
Вычислить выражение expr без отображения пустых (void) возвращенных значений.

Вы можете использовать этот вариант команды print, если хотите выполнить функцию из вашей программы, не засоряя вывод пустыми возвращенными значениями. Если результат не пустой (void), он выводится и сохраняется в истории значений.

Устанавливаемая пользователем переменная call_scratch_address задает положение рабочей области, которая будет использоваться, когда GDB вызывает функцию на целевой машине. Это необходимо, так как обычный метод размещения рабочей области в стеке не работает в системах с раздельными областями команд и данных.

Внесение изменений в программу

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

Если вы хотите иметь возможность исправлять двоичный код, вы можете указать это явно с помощью команды set write. Например, вы можете захотеть установить внутренние флаги отладки или даже сделать аварийные исправления.

set write on
set write off
Если вы установите set write в состояние on, GDB открывает исполняемые файлы и файлы дампов памяти в режиме для чтения и записи; если вы введете set write off (устанавлено по умолчанию), GDB открывает их в режиме только для чтения.

Если вы уже загрузили файл, то после установки set write вам необходимо загрузить его снова (используя команды exec-file или core-file), чтобы новые установки вступили в силу.
show write
Показать, открыты исполняемые файлы и файлы дампов памяти для записи или нет.




Предыдущий раздел: Тематические статьи