Учебные программы » Системы реального времени » Дополнительные материалы » Отладка с использованием GDB
Отладка с использованием GDB
Отладка с использованием GDB ================================================================ Версия 4.15 - 2 - Отладка с помощью GDB Этот файл описывает GDB - символический GNU-отладчик. Версия 4.15. Общие сведения о GDB Цель отладчика типа GDB - позволить Вам увидеть, что происходит "внутри" какой-либо программы во время ее выполнения или в момент нарушения ее работы. GDB способен выполнять четыре основных типа действий (а также другие, поддерживающие основные), чтобы помочь Вам выявить ошибку. * Начать выполнение вашей программы, особо отметив что-то, что возможно влияет на ее поведение. * Остановить вашу программу при указанных условиях. * Исследовать, что случилось в момент останова. * Изменить вашу программу таким образом, что экспериментально исправив проявление одной ошибки, продолжить выявление следующих. Вы можете использовать GDB для отладки программ, написанных на C или C++. Для получения большей информации см.Раздел 9.4.1 [C и C++]. GDB частично поддерживает языки Modula-2 и Chill. Для получения информации относительно Modula-2 см.Раздел 9.4.2 [Modula-2]. Относительно Chill более подробной документации нет. Отлаживание программ на Паскале, использующих множества, поддиапазоны, файловые переменные или рекурсивные функции, в настоящее время невозможно. GDB не поддерживает ввод выражений, вывод значений или подобные особенности, использующие синтаксис Паскаля. - 3 - GDB может использоваться для отладки программ, написанных на Фортране, хотя он еще не поддерживает ввод выражений, вывод значений или подобные особенности, использующие синтаксис Фортрана. Может быть необходимо обратиться к некоторым переменным c литерой подчеркивания в конце имени. 1. Пример работы GDB Небольшого количества команд, описанных в этой главе, вполне достаточно, чтобы начать пользоваться отладчиком. В одной из предварительных версий программы GNU `m4' (родовой макропроцессор) была допущена следующая ошибка: иногда, при замене стандартных кавычек, команды, использующие одно макроопределение вместо другого, прекращали работать. В пробном запуске `m4' мы определили макропараметр `foo', который расширялся до `0000', а затем использовали внутреннюю для `m4' поцедуру `defn', чтобы определить `bar' как то же самое. Однако, когда мы изменили открывающую кавычку на `' и закрывающую на `', та же самая процедура не смогла определить новый синоним `baz'. $ cd gnu/m4 $ ./m4 define(foo,0000) foo 0000 define(bar,defn(`foo')) bar 0000 changequote( ,) define(baz,defn( foo)) baz C-d - 4 - m4: End of input: 0: fatal error: EOF in string Попытаемся с помощью GDB понять, что произошло. $ gdb m4 GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15, Copyright 1995 Free Software Foundation, Inc... (gdb) GDB читает минимум символьных данных, чтобы знать, где в случае необходимости найти остальные; в результате первое сообщение появляется очень быстро. Теперь мы хотим установить для GDB меньшую, чем обычно, ширину экрана, с тем, чтобы примеры помещались на страницах этого руководства. (gdb) set width 70 Нам необходимо увидеть, как работает внутренняя процедура `changequote'. Из исходного текста мы знаем, что нужно заострить внимание на подпрограмме `m4_changequote'. Мы устанавливаем там точку останова с помощью команды GDB `break'. (gdb) break m4_changequote Breakpoint 1 at 0x62f4: file builtin.c, line 879. Используя комманду `run', мы запускаем `m4' под управлением GDB; программа выполняется, как обычно, пока управление не достигнет подпрограммы `m4_changequote': - 5 - (gdb) run Starting program: /work/Editorial/gdb/gnu/m4/m4 define(foo,0000) foo 0000 Чтобы вызвать точку останова, мы набираем `changequote'. GDB приостановил выполнение `m4', выведя на экран информацию о том месте, где он остановился. changequote( ,) Breakpoint 1, m4_changequote (argc=3, argv=0x33c70) at builtin.c:879 879 if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3)) Теперь мы используем комманду `n' (`next'), чтобы выполнить следующую строку текущей функции. (gdb) n 882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])\ : nil, Похоже, что `set_quotes' - нужная нам подпрограмма. Мы можем войти в нее с помощью команды `s' (`step') вместо `next'. `step' переходит на следующую исполняемую строку любой подпрограммы, в данном примере она входит в `set_quotes'. (gdb) s set_quotes (lq=0x34c78 " ", rq=0x34c88 "") at input.c:530 530 if (lquote != def_lquote) Отображение подпрограммы (с параметрами), в то время как `m4' приостановлена, называется отображением процедурной секции. Оно показывает краткие сведения о секции. Мы можем использовать команду `backtrace' (которую можно сократить до `bt'), чтобы посмотреть, где - 6 - мы находимся в процедурном стеке: команда `backtrace' выводит процедурную секцию каждой активной подпрограммы. (gdb) bt #0 set_quotes (lq=0x34c78 " ", rq=0x34c88 "") at input.c:530 #1 0x6344 in m4_changequote (argc=3, argv=0x33c70) at builtin.c:882 #2 0x8174 in expand_macro (sym=0x33320) at macro.c:242 #3 0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30) at macro.c:71 #4 0x79dc in expand_input () at macro.c:40 #5 0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195 Мы проходим еще несколько строк. Первые два раза мы можем использовать команду `s'; затем два раза пользуемся командой `n', чтобы избежать вхождения в подпрограмму `xstrdup'. (gdb) s 0x3b5c 532 if (rquote != def_rquote) (gdb) s 0x3b80 535 lquote = (lq == nil || *lq == '\0') ? \ def_lquote : xstrdup(lq); (gdb) n 536 rquote = (rq == nil || *rq == '\0') ? def_rquote\ : xstrdup(rq); (gdb) n 538 len_lquote = strlen(rquote); Последняя выведенная строка выглядит немного странно; мы можем исследовать переменные `lquote' и `rquote', чтобы понять, действительно ли это определенные нами новые левая и правая кавычки. Мы используем команду `p' (`print'), чтобы вывести их значения. (gdb) p lquote $1 = 0x35d40 " " (gdb) p rquote $2 = 0x35d50 "" - 7 - `lquote' и `rquote' действительно заменяют новые кавычки. Для просмотра контекста, мы можем вывести десять строк источника, окружающих текущую строку, командой `l' (`list'). (gdb) l 533 xfree(rquote); 534 535 lquote = (lq == nil || *lq == '\0') ? def_lquote\ : xstrdup (lq); 536 rquote = (rq == nil || *rq == '\0') ? def_rquote\ : xstrdup (rq); 537 538 len_lquote = strlen(rquote); 539 len_rquote = strlen(lquote); 540 } 541 542 void Пройдем еще две строки, устанавливающие `len_lquote' и `len_rquote', затем исследуем значения этих переменных. (gdb) n 539 len_rquote = strlen(lquote); (gdb) n 540 } (gdb) p len_lquote $3 = 9 (gdb) p len_rquote $4 = 7 В этом месте, очевидно, кроется ошибка, так как `len_lquote' и `len_rquote' предполагались той же длины, что и `lquote' и `rquote' соответственно. Мы можем присвоить им лучшие значения, используя команду `p', так как она выводит результат любого выражения, а выражение может содержать подпрограммы вызова и присваивания. - 8 - (gdb) p len_lquote=strlen(lquote) $5 = 7 (gdb) p len_rquote=strlen(rquote) $6 = 9 Достаточно ли этого, чтобы решить проблему использования новых кавычек во внутренней процедуре `defn'? Мы продолжаем выполнение `m4' командой `c' (`continue') и испытываем пример, вызвавший первоначальную ошибку: (gdb) c Continuing. define(baz,defn( foo)) baz 0000 Успех! Новые кавычки теперь работают так же хорошо, как и стандартные. Оказалось, что проблема заключалась в неправильном определении длины для двух типов. Мы позволяем `m4' выйти, давая ему команду EOF вводом: C-d Program exited normally. Сообщение `Program exited normally.' идет от GDB. Оно показывает, что выполнение `m4' завершено. Мы можем закончить работу с GDB командой `quit'. (gdb) quit - 9 - 2. Вход и выход из GDB Эта глава посвящена входу и выходу из GDB. Основные принципы: * набрать `gdb' для начала работы GDB. * набрать `quit' или `C-d' для ее завершения. 2.1. Вызов GDB GDB вызывается запуском программы `gdb'. Начав работу, GDB считывает команды с терминала, пока Вы не завершите сеанс. Вы можете запустить `gdb' с рядом параметров и опций, с самого начала установив большую часть среды отлаживания. Опции командной строки, описанные здесь, предназначены для различных ситуаций; в некоторых средах ряд опций в действительности может быть недоступен. Чаще всего GDB запускают с одним параметром, который определяет исполняемую программу. gdb PROGRAM Вы также можете одновременно указать исполняемую программу и файл дампа памяти. gdb PROGRAM CORE Вы можете на месте второго параметра указать идентификатор процесса (process ID), если хотите отладить выполнение процесса: gdb PROGRAM 1234 GDB будет работать с процессом `1234' (если, конечно, у вас нет файла с именем `1234'; GDB вначале проверяет наличие файла дампа памяти с - 10 - таким именем). Преимущества второго параметра командной строки заметны только при наличии довольно совершенной операционной системы; если Вы используете GDB как удаленный отладчик, присоединенный к простому процессору, может вообще не быть никакого понятия "процесса" и часто нет никакого способа получить дамп. Вы можете запустить `gdb' без вывода начальных сообщений, описывающих отсутствие гарантии на GDB, указав `-silent': gdb -SILENT Кроме того, Вы можете контролировать запуск GDB с помощью опций командной строки. GDB сам напомнит вам о всех доступных опциях. Наберите gdb -help чтобы вывести все доступные опции и краткое описание их использования на экран (`gdb -h' - сокращенный эквивалент). Все данные вами опции и параметры командной строки выполняются последовательно. При использовании опции `-x' важен их порядок. 2.1.1. Выбор файлов При запуске GDB считывает параметры, не относящиеся к опциям, как указатели на исполняемую программу и посмертный дамп (или идентификатор процесса), точно так же, как если бы эти параметры сопровождались опциями `-se' и `-c' соответственно. (GDB считает первый параметр, не связанный с флагом опции, эквивалентом опции `-se', сопровождаемой параметром; второй такой параметр, если он есть, - эквивалентом опции `-c', сопровождаемой параметром.) - 11 - У многих опций есть как длинная, так и краткая формы; обе приводятся в нижеследующем списке. GDB также распознает недвусмысленные сокращения длинных форм. (По желанию Вы можете сопровождать флаги опций знаком "--" вместо "-"; мы же будем использовать чаще употребляемый формат.) `-symbols FILE' `-s FILE' Читать таблицу символов из файла FILE. `-exec FILE' `-e FILE' Использовать файл FILE, по необходимости, либо как исполняемый файл, либо для исследования неизменяемых данных вместе с дампом памяти. `-se FILE' Читать таблицу символов из файла FILE и использовать ее как исполняемый файл. `-core FILE' `-c FILE' Использовать файл FILE как дамп памяти для исследования. `-c NUMBER' Подсоединиться к процессу NUMBER, как по команде `attach' (если только нет файла в формате дампа памяти под именем NUMBER; в этом случае `-c' указывает на этот файл, как на требуемый дамп для считывания). `-command FILE' `-x FILE' Выполнить команд GDB из файла FILE. См.Раздел 15.3 [Командные файлы]. - 12 - `-directory DIRECTORY' `-d DIRECTORY' Добавить DIRECTORY к путям поиска файлов с исходными текстами. `-m' `-mapped' *Предупреждение: эта опция зависит от особенностей ОС.* Если на вашей системе осуществим (через системный вызов " mmap ") доступ к области памяти посредством механизма доступа к файлу, Вы можете использовать эту опцию, чтобы GDB записал символы из вашей программы в файл многократного использования в текущем каталоге. Если программа, которую Вы отлаживаете, называется "/tmp/fred", отображенный символьный файл будет назван "./fred.syms". В следующих сеансах GDB-отладки будет отмечено наличие этого файла и информация из него будет переведена в символьную, что быстрее, чем чтение таблицы символов из исполняемого файла. Для главной машины, на которой запускается GDB, `.syms' файл - особый. Он содержит точное отображение внутренней таблицы символов GDB и не может быть разделен между несколькими главными платформами. `-r' `-readnow' Читать файл, содержащий таблицу символов, сразу целиком, а не стандартным образом, когда он считывается постепенно по мере необходимости. Эта команда замедляет запуск, но дальнейшие операции производятся быстрее. Комбинирование опций `-mapped' и `-readnow' используется при создания файла `.syms', содержащего полную символьную информацию. (См.Раздел 12.1 [Команды для определения файлов]) gdb -batch -nx -mapped -readnow programname - 13 - 2.1.2. Выбор режима Вы можете запускать GDB в различных альтернативных режимах; например, в пакетном или "тихом". `-nx' `-n' Не выполнять команды ни из каких установочных файлов (обычно назваемых `.gdbinit'). Обычно, команды из этих файлов выполняются после обработки всех командных опций и параметров. См.Раздел 15.3 [Командные файлы]. `-quiet' `-q' "Тихий". Не печатать вводное сообщение и информацию об авторских правах. Эти сообщения также подавляются в пакетном режиме. `-batch' Запуск в пакетном режиме. Выход с состоянием `0' после выполнения всех командных файлов, сопровождаемых опцией `-x' (и всех команд из установочных файлов, если нет отмены `-n'). Выход с ненулевым состоянием, если во время выполнения команд из командных файлов произошла ошибка. Пакетный режим может быть использован для запуска GDB в режиме фильтра; например, чтобы загрузить и запустить программу на другом компьютере. Для большего удобства сообщение Program exited normally. (которое обычно выдается при завершении программы, исполняемой под управлением GDB) в пакетном режиме не выдается. `-cd DIRECTORY' Запустить GDB, используя DIRECTORY как рабочий каталог, вместо текущего. - 14 - `-fullname' `-f' GNU Emacs устанавливает эту опцию, когда запускает GDB как подпроцесс. GDB выводит полное имя файла и номер строки в стандартном, распознаваемом режиме, всякий раз, когда выводится процедурная секция (включая каждую остановку вашей программы). Вывод в распознаваемом формате выглядит, как два символа "\032", которые сопровождаются именем файла, номером строки и символьной позицией, разделенными двоеточиями, а затем совершается переход на новую строку. Программа интерфейса Emacs-to-GDB использует два символа "\032", как сигнал для отображения исходного текста данной секции. `b BPS' Установить скорость передачи (скорость в бодах - количество бит в секунду) любого последовательного интерфейса, используемого GDB для удаленной отладки. `-tty DEVICE' Использвать устройство DEVICE для стандартного ввода-вывода вашей программы. 2.2. Выход из GDB `quit' Чтобы покинуть GDB, используйте команду `quit' (сокращенно `q'), или наберите "литеру конца файла" [end-of-file] (обычно `C-d'). Если Вы не добавляете никакого выражения EXPRESSION, GDB нормально завершит работу; в противном случае он завершит работу, используя результат EXPRESSION как код ошибки. Прерывания (часто `C-c') не выводят из GDB, но завершают действие любой команды GDB и возвращают на командный уровень GDB. Вы можете безбоязненно пользоваться прерываниями, т.к. GDB реагирует на них только если они безопасны. - 15 - Если Вы использовали GDB для управления присоединенным процессом или внешним устройством, Вы можете освободить его командой `detach'. (См.Раздел 4.7 [Отлаживание запущенного процесса]). 2.3. Команды Shell Если Вам поднадобилось выполнить команды Shell в течение сеанса GDB-отладки, не обязательно приостанавливать работу или выходить из GDB. Вы можете воспользоваться командой `shell'. `shell COMMAND STRING' Вызвать Shell, чтобы выполнить COMMAND STRING. Системная переменная `SHELL', если она есть, определяет, какой оболочкой воспользоваться. В противном случае GDB использует "/bin/sh". В среде разработки часто бывает необходимо воспользоваться утилитой `make'; для нее команда `shell' необязательна: `make MAKE-ARGS' Выполнить программу ` make ' с определенными параметрами. Эта строка эквивалентна строке `shell make MAKE-ARGS'. 3. Команды GDB Вы можете сокращать команды GDB по первым символам, если это сокращение однозначно; некоторые команды GDB Вы можете повторить просто нажатием RET. Вы можете также использовать TAB, чтобы GDB заполнил остальную часть слова в команде (или показал Вам доступные варианты, если имеется несколько возможностей). - 16 - 3.1. Командный синтаксис Формат команды GDB - одна вводимая строка. Никаких ограничений на ее длину нет. Строка начинается именем команды, сопровождающимся параметрами, значение которых зависит от команды. Например, команда `step' допускает параметр, определяющий количество шагов: `step 5'. Также можно использовать команду `step' и без параметров. Некоторые команды не допускают никаких параметров. Всегда, пока сохраняется однозначность, имя команды GDB можно сокращать. В документации для отдельных команд перечислены особые сокращения. В некоторых случаях позволяются даже двусмысленные аббревиатуры. Например, несмотря на то, что с буквы `s' начинается несколько команд, `s' специально определена, как эквивалент команды `step'. Вы можете протестировать сокращение, используя его как параметр команды `help'. Введенная пустая строка (простое нажатие RET) означает повтор предыдущей команды. Некоторые команды (например, `run') таким способом не повторяются; это команды, непреднамеренное повторение которых может вызвать нарушение в работе. Команды `list' и `x', если Вы повторяете их нажатием RET, вместо точного повтора создают новые параметры, что позволяет легко просматривать исходный текст или память. GDB также использует RET по-другому - для разделения на части результата большого размера, подобно общей утилите `more' (См.Раздел 14.4 [Размер экрана]). Так как в этой ситуации легко лишний раз нажать RET, GDB блокирует повтор команд сразу после любой команды, генерирующей такой тип экрана. Любой текст, идущий после `#' (и до конца строки) считается комментарием и ничего не значит. Символ `#' используется в основном в командных файлах. (См.Раздел 15.3 [Командные файлы]). - 17 - 3.2. Завершение команды GDB может заполнить за Вас недостающую часть командного слова, если оно однозначно; он также может показать всевозможные продолжения команды. Это правило распространяется на команды и подкоманды GDB, а также на символьные имена вашей программы. Если Вы хотите, чтобы GDB заполнил недостающую часть слова, нажмите TAB. Если возможность только одна, GDB дополнит слово и будет ждать от Вас окончания команды (или нажатия RET для ввода строки). Например, если Вы наберете (gdb) info bre TAB GDB дополнит слово до `breakpoints', так как это единственная подкоманда команды `info', начинающаяся на `bre': (gdb) info breakpoints Теперь Вы можете либо нажать RET, чтобы выполнить команду `info breakpoints', либо нажать "backspace" и ввести что-нибудь еще, если `info breakpoints' не похожа на нужную Вам команду. (Если Вы сразу были уверены, что Вам нужна именно `info breakpoints', Вы могли бы нажать RET, использовав сокращение вместо полной команды). Если при нажатии TAB для следующего слова есть несколько возможностей, GDB издает звенящий звук. Вы можете либо добавить несколько символов и попытаться снова, либо снова нажать TAB; тогда GDB выведет все возможности. Например, Вы хотите установить точку останова на подпрограмме, имя которой начинается на `make_', но когда Вы набираете `b make_TAB', Вы слышите звоночек GDB. Повторным нажатием TAB на экран выводятся все имена функций в вашей программе, начинающиеся с этих символов: (gdb) b make_ TAB - 18 - 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 повторяет введенную Вами строкую. Таким образом, Вы можете закончить команду. Если Вы хотите сразу увидеть список альтернатив, Вы можете, вместо повторного нажатия TAB, набрать `M-?', что означает `META ?'. Набрать это Вы можете, либо как `?' при нажатой клавише META shift (если она есть на вашей клавиатуре), либо как ESC, сопровождаемый `?'. Иногда Вам нужно ввести слово, содержащее скобки или другие символы, которые GDB обычно запрещает использовать внутри слова. В этом случае при включении слова в команду GDB его выделяют одиночными кавычками ('). Чаще всего такая ситуация возникает, когда Вам нужно набрать имя функции C++, так как C++ допускает перегружение функций (повторные определения одной и той же функции, различаемые по типу параметра). Например, когда Вы устанавливаете точку останова, необходимо различать, нужен ли Вам вариант `name', обрабатывающий параметр `int' (`name(int)'), или вариант, работающий с параметром `float' (`name(float)'). Чтобы в этой ситуации использовать средства завершения слова, наберите перед именем функции одиночную кавычку ('), которая сообщает GDB о том, что при нажатии TAB или `M-?' может потребоваться рассмотрение большего количества информации, чем обычно: (gdb) b 'bubble( M-? bubble(double,double) bubble(int,int) (gdb) b 'bubble( - 19 - В некоторых случаях GDB сам сообщает, что для завершения имени требуется использование кавычек. В таких случаях GDB (дополнив, насколько возможно) вставляет кавычку за Вас, если Вы не напечатали ее сразу: (gdb) b bub TAB GDB изменяет введенную Вами строку и звенит: (gdb) b 'bubble( В общем, GDB сообщает, что кавычка необходима (и вставляет ее), если Вы, не начав еще набирать список параметров, просите дополнить перегруженный символ. 3.3. Получение справки Вы всегда можете запросить информацию относительно команд 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 - 20 - 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' Использовав один из основных классов, как параметр `help', Вы можете получить список команд этого класса. В этом примере выведена информация по классу `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' Если в качестве параметра `help' стоит имя команды, GDB выводит сведения об использовании этой команды. `complete ARGS' Команда `complete ARGS' выдает список всевозможных завершений для данного начала команды. ARGS определяет первые символы команды, которую Вы желаете завершить. Например: complete i - 21 - приводит к выводу: info inspect ignore Эта команда предназначена для использования при работе с GNU Emacs. Кроме `help', Вы можете использовать команды `info' и `show', чтобы запросить о состоянии вашей программы или GDB. Обе команды поддерживают несколько вариантов запросов; они представлены в этом руководстве с соответствующим контекстом. Все подкоманды можно найти в списках под словами `info' и `show' в разделе "Index" (последний раздел). См.[Index]. `info' Эта команда (сокращенно `i') описывает состояние вашей программы. Например, `info args' выводит список параметров, заданных вашей программе; `info registers' - список регистров, используемых в данный момент; `info breakpoints' - список установленных точек останова. С помощью `help info' Вы можете получить полный перечень подкоманд `info'. `set' С помощью `set' Вы можете присвоить значение какого-нибудь выражения какой-нибудь системной переменной. Например, Вы можете установить значение $-sign как GDB-сообщение командой `set prompt $'. `show' В отличие от `info', show' описывает состояние непосредственно GDB. Большую часть информации, показываемой `show', Вы можете изменять используя соответствующую команду `set'; например, вы можете изменить систему счисления, используемую для вывода информации, командой `set radix', или запросить о том, какая в данный момент используется, командой `show radix'. - 22 - Чтобы вывести значения всех устанавливаемых параметров, Вы можете воспользоваться командой `show' без параметров или командой `info set'. В обоих случаях Вы получите одну и ту же информацию. Есть три подкоманды `show', для которых нет соответствующих команд `set'. `show version' Показать номер версии GDB. Вам следует включить эту информацию в отчеты GDB об ошибках. Если у Вас установлено несколько версий GDB, Вы, возможно, захотите определить, какую версию GDB вы запустили; в более поздних версиях GDB появляются новые команды, тогда как старые отмирают. Номер версии объявляется также и при запуске GDB. `show copying' Отобразить информацию относительно разрешения на копирование GDB. `show warranty' Отобразить заявление GNU об отсутствии гарантии. 4. Выполнение программ под управлением GDB Когда Вы запускаете программу под управлением GDB, Вы должны сначала при компилировании сгенерировать информацию об отладке. Вы можете запустить GDB с параметрами в среде по вашему выбору. Вы можете переадресовать ввод-вывод вашей программы, отладить уже запущенный процесс или уничтожить порожденный процесс. - 23 - 4.1. Компилирование для отладки Во время компиляции, чтобы потом эффективно отлаживать программу, Вам необходимо сгенерировать отладочную информацию. Эта информация сохраняется в объектном файле; она описывает тип данных каждой переменной или функции и соответствие между исходными номерами строк и адресами в исполнимом коде. Укажите опцию `-g' при запуске компилятора, чтобы запросить отладочную информацию. Многие компиляторы C неспособны одновременно обрабатывать опции `-g' и `-O'. Вы не сможете сгенерировать оптимизированные исполнимые программы, содержащие отладочную информацию, используя такие компиляторы. GCC, GNU-транслятор C, поддерживает опцию `-g' с `-O' или без нее, давая возможность отладить оптимизированную программу. Мы рекомендуем Вам компилировать программу всегда с опцией `-g'. Вы можете думать, что ваша программа верна, однако бессмысленно на этом настаивать. Когда Вы отлаживаете программу, откомпилированную с `-g -O', помните, что оптимизатор перестроил ваш текст; отладчик показывает то, что там находится в действительности. Не удивляйтесь, если порядок выполнения не будет точно соответствовать исходному файлу! Критический пример: Если Вы определите нигде не используемую переменную, GDB никогда ее не заметит, потому что при оптимизации компилятор исключит ее. Некоторые вещи, особенно на машинах с планированием инструкций, лучше выполняются при компилировании с `-g', а не с `-g -O'. Если у Вас возникли сомнения, перекомпилируйте программу еще раз с одной опцией `-g'. Если трудности не исчезнут, пожалуйста, пришлите нам сведения об этой ошибке (включив тестовый случай!). В ранних версиях GNU-компилятора C для отладочной информации встречается вариант опции `-gg'. GDB больше не поддерживает этот формат; если в вашем GNU-компиляторе C есть такая опция, не - 24 - пользуйтесь ею. 4.2. Запуск вашей программы `run' `r' Используйте команду `run', чтобы запустить вашу программу под управлением GDB. Сначала Вы должны определить имя программы (исключая работы на VxWorks), задав его как параметр для GDB (См.Главу 2 [Вход и выход из GDB]), или используя команду `file' или `exec-file' (См.Раздел 12.1 [Команды для определения файлов]) Если Вы запускаете вашу программу в среде выполнения, поддерживающей процессы, `run' создает младший процесс (inferior process), который выполняет вашу программу. (В среде без процессов, `run' сразу переходит к запуску вашей программы). Выполнение программы зависит от некоторой информации, получаемой с высших уровней. GDB обеспечивает способы получения этой информации, которую Вы должны создать перед запуском вашей программы. (Вы можете менять ее после запуска, но подобные изменения не повлияют на текущее исполнение программы). Эту информацию можно разделить на четыре категории: Аргументы. Определите аргументы, задаваемые вашей программе, как параметры команды `run'. Если имеется в наличии shell, она используется для передачи аргументов, т.о., Вы можете использовать нормальные соглашения (такие, как расширения группового символа или замена переменной) в описании аргументов. В ОС Unix, Вы можете выбрать используемую shell с помощью системной переменной `SHELL'. См.Раздел 4.3 [Аргументы вашей программы]. - 25 - Рабочая среда. Обычно ваша программа наследует рабочую среду из GDB, но Вы можете использовать команды `set environment' и `unset environment', чтобы изменить часть среды, влияющую на вашу программу. См.Раздел 4.4 [Рабочая среда вашей программы]. Рабочий каталог. Ваша программа наследует рабочий каталог из GDB. Вы можете установить рабочий каталог GDB командой `cd'. (См.Раздел 4.5 [Рабочий каталог вашей программы]). Стандартный ввод-вывод. Для стандартного ввода-вывода ваша программа обычно использует то же устройство, что и GDB. Вы можете переадресовать ввод-вывод в командной строке `run' или использовать команду `tty', чтобы назначить для вашей программы другое устройство. См.Раздел 4.6 [Ввод-вывод вашей программы]. Предупреждение: В то время, как происходит переназначение ввода-вывода, Вы не можете использовать каналы передачи выходных данных отлаживаемой программы другой программе; если Вы попытаетесь так сделать, вероятнее всего, GDB закончит отладку неправильной программы. Ваша программа начинает выполняться непосредственно после команды `run'. См.Главу 5 [Остановка и продолжение исполнения], для получения информации о том, как остановить программу. Однажды остановив вашу программу, Вы можете командами `print' и `call' вызывать функции из нее. См.Главу 8 [Исследование данных]. Если время модификации вашего символьного файла изменилось с последнего его считывания GDB, GDB сбрасывает его таблицу символов и читает ее снова. При этом GDB пытается сохранить точки останова. - 26 - 4.3. Аргументы вашей программы Аргументы вашей программы могут быть определены параметрами команды `run'. Они передаются shell, которая расширяет групповые символы и выполняет переадресацию ввода-вывода, а потом передает их вашей программе. Системная переменная `SHELL', если она есть, определяет, какую оболочку использовать. Если `SHELL' не определена, GDB использует `/bin/sh'. Команда `run', запущенная без параметров, использует параметры предыдущего использования `run' или параметры, установленные командой `set args'. `set args' Определить аргументы последующего запуска вашей программы. Если у `set args' параметров нет, `run' исполняет программу без аргументов. Если Вы хоть раз запускали программу с аргументами, единственный способ выполнить ее без них - это воспользоваться `set args' перед следующим запуском. `show args' Показать аргументы, задаваемые вашей программе при запуске. 4.4. Рабочая среда вашей программы Рабочая среда задается набором системных переменных и их значениями. Системные переменные традиционно описывают ваше пользовательское имя, ваш домашний каталог, тип терминала и пути поиска исполняемой программы. Обычно системные переменные задаются в оболочке и наследуются всеми запускаемыми программами. При отладке иногда бывает полезно выполнить программу в измененной рабочей среде, не перезапуская GDB. - 27 - `path DIRECTORY' Добавить DIRECTORY в начало системной переменной `PATH' (пути поиска исполняемых программ), как для GDB, так и для вашей программы. Вы можете указать сразу несколько каталогов, разделяя их `:' или пробелом. Если какой-то каталог уже присутствует, он перемещается в начало списка, так что поиск в нем осуществляется раньше, чем прежде. С помощью строки `$cwd' Вы можете при поиске путей обратиться к текущему рабочему каталогу. Если вместо нее Вы используете `.', Вы обратитесь к каталогу, из которого Вы выполняли команду `path'. GDB заменяет `.' в параметре DIRECTORY (на текущий путь), прежде, чем добавит DIRECTORY к путям поиска. `show paths' Отобразить перечень поиска путей для исполнимых программ (т.е., значение системной переменной `PATH'). `show environment [VARNAME]' Вывести значение системной переменной VARNAME, которое задается вашей программе при запуске. Если VARNAME отсутствует, выведутся имена и значения всех системных переменных, задаваемых вашей программе. Вы можете сократить `environment' до `env'. `set environment VARNAME [=] VALUE' Присвоить системной переменной VARNAME значение VALUE. Значение изменяется только для вашей программы, но не для GDB. VALUE может быть любой строкой; значение системной переменной - строка, интерпретируемая непосредственно вашей программой. Параметр VALUE необязателен; если он отсутствует, Переменной присваивается нулевое значение. Например, команда: set env USER = foo сообщает программе Unix, что, при последующем выполнении, имя пользователя - `foo'. (Пробелы вокруг `=' поставлены для ясности; в - 28 - действительности они не требуются). `unset environment VARNAME' Удалить переменную VARNAME из рабочей среды вашей программы. Эта команда отличается от `set env VARNAME =', которая присваивает пустое значение, тогда как `unset environment' вообще удаляет переменную из рабочей среды. Предупреждение: GDB управляет вашей программой, используя shell, указанный системной переменной `SHELL', если она есть (или `/bin/sh', если нет). Если переменная `SHELL' указывает shell, использующий инициализационный файл - такой, как `.cshrc', для C-shell, или `.bashrc' для BASH - любые переменные, установленные в этом файле, влияют на вашу программу. Вы можете переместить установку системных переменных в файлы, которые выполняются только при особом сигнале, подобно `.login' или `.profile'. 4.5. Рабочий каталог вашей программы Каждый раз при запуске вашей программы командой `run', рабочий каталог наследуется из текущего рабочего каталога GDB. Первоначально рабочий каталог GDB наследуется из порождающего процесса (parent process) (обычно, shell), но вы можете определить новый рабочий каталог GDB командой `cd'. Рабочий каталог GDB служит каталогом, используемым по умолчанию командами, которые определяют, с какими файлами должен работать GDB. См.Раздел 12.1 [Команды для определения файлов]. `cd DIRECTORY' Установить DIRECTORY рабочим каталогом GDB. `pwd' Вывести имя рабочего каталога GDB. - 29 - 4.6. Ввод-вывод вашей программы По умолчанию, программа, запущенная под GDB, использует для ввода-вывода то же устройство, что и GDB. GDB переключает устройства для общения с Вами, но он запоминает устройство ввода-вывода вашей программы и возвращается к нему, когда Вы продолжаете выполнение вашей программы. `info terminal' Отображает информацию, записанную GDB, относительно устройства ввода-вывода, используемого вашей программой. Вы можете переадресовать ввод и/или вывод вашей программы, используя переадресацию оболочки с помощью команды `run'. Например: run > outfile запускает вашу программу, используя для вывода файл `outfile'. Ввод-вывод вашей программы можно определить другим способом - с помощью команды `tty'. Эта команда принимает в качестве параметра имя файла, имя которого будет использоваться по умолчанию при следующей команде `run'. `tty' также назначает устройство ввода-вывода для порожденных командой `run' процессов. Например: tty /dev/ttyb назначает для процессов, запускаемых следующей командой `run', `/dev/ttyb', как стандартное устройство ввода-вывода и как собственное устройство отображения. Явная переадресация в команде `run' отменяет действие команды `tty' на устройство ввода-вывода, но сохраняет ее действие на устройство отображения. - 30 - При использовании команды `tty' или при переадресации в команде `run', Вы влияете на ввод только вашей программы. Ввод для GDB по прежнему выполняется с вашего терминала. 4.7. Отладка запущенного процесса `attach PROCESS-ID' Эта команда подсоединяет к исполняемому процессу, который был запущен вне GDB. (Их список показывается командой `info files'). Команда принимает в качестве параметра идентификатор процесса. Обычный способ выяснить идентификатор процесса Unix - использовать утилиту `ps' или команду shell `jobs -l'. При повторном нажатии RET команда `attach' не повторяется. Для использования `attach' необходимо, чтобы ваша программа была запущена в среде, поддерживающей процессы. Например, `attach' не сработает для программы на пустой целевой плате без какой-нибудь операционной системы. Также должна быть разрешена передача сигналов процессу. При использовании `attach', Вам следует сначала определить командой `file' программу, запускаемую в процессе, и загрузить ее таблицу символов. См.Раздел 12.1 [Команды для определения файлов]. Первое, что GDB делает для отладки процесса - останавливает его. Вы можете изучать и изменять присоединенный процесс всеми командами, доступными при запуске процесса командой `run'. Вы можете устанавливать точки останова, Вы можете продолжать выполнение или осуществлять его пошагово; Вы можете изменять память. Если Вы желаете, чтобы процесс продолжал выполняться, вы можете после его присоединения воспользоваться командой `continue'. - 31 - `detach' Когда Вы закончили отладку присоединенного процесса, Вы можете воспользоваться командой `detach', чтобы высвободить его из-под управления GDB. Освобожденный процесс продолжает выполняться. После команды `detach', процесс и GDB становятся полностью независимыми друг от друга, и теперь Вы можете присоединить другой процесс (`attach') или начать его выполнение командой `run'. При повторном нажатии RET команда `detach' не повторяется. Если Вы выходите из GDB или выполняете команду `run', в то время, как у Вас есть присоединенный процесс, он уничтожается. По умолчанию, GDB запрашивает подтверждение при попытке сделать что-либо подобное; Вы можете контролировать запрос подтверждения командой `set confirm'. (См.Раздел 14.6 [Необязательные предупреждения и сообщения]). 4.8. Уничтожение порожденнного процесса `kill' Уничтожить порожденнный процесс, в котором ваша программа выполняется под управлением GDB. Эта команда полезна, если Вы желаете отладить посмертный дамп, а не исполняемый процесс, т.к. во время выполнения вашей программы, GDB игнорирует любую аварийную выдачу. В некоторых операционных системах программа не может быть выполнена не под управлением GDB, если Вы установили на ней точки останова во время сеанса GDB-отладки. В этой ситуации вы можете использовать команду `kill', чтобы разрешить исполнение вашей программы вне отладчика. Команда `kill' также полезна, если Вы желаете перекомпилировать и перекомпоновать вашу программу, так как во многих системах невозможно изменить исполняемый файл, пока он запущен в процесс. В этом случае, когда Вы снова наберете `run', GDB отметит, что файл был изменен, и - 32 - заново считает его таблицу символов (при этом он попытается сохранить текущую установку точек останова). 4.9. Дополнительная информация о процессе Некоторые операционные системы обеспечивают средство `/proc', которое может быть использовано для изучения изображения исполняемого процесса, используя подпрограммы файловой системы. Если GDB сконфигурирован для операционной системы с таким средством, команда `info proc' выдает некоторую информацию о процессе, выполняющем вашу программу. `info proc' работает только в системах SVR4, которые поддерживают `procfs'. `info proc' Перечень доступной информации относительно процесса. `info proc mappings' Отчет о диапазоне адресов, доступных в программе, с информацией для каждого диапазона о том, может ли программа считывать, записывать или выполнять его. `info proc times' Начальное время, время пользователя ЦП (CPU) и время системного ЦП для вашей программы и дочерних записей. `info proc id' Отчет об идентификаторах процессов, связанных с вашей программой: идентификатор собственного процесса, идентификатор порождающего процесса, идентификатор группового процесса и идентификатор сеанса. `info proc status' Общая информация относительно состояния процесса. Если процесс остановлен, этот отчет включает причину остановки и все полученные сигналы. - 33 - `info proc all' Показать всю вышеупомянутую информацию о процессе. 4.10. Отладка программ с несколькими потоками В некоторых операционных системах у одиночной программы может быть более одного потока исполнения. Точная семантика потоков меняется в зависимости от операционной системы, но в основном потоки одиночной программы родственны системным процессам, за исключением того, что они используют одно адресное пространство (то есть, они могут использовать одни и те же переменные). С другой стороны, у каждого потока есть свои собственные регистры и процедурные стеки, и, возможно, отдельная память. GDB обеспечивает следующие средства для отладки многопотоковых программ: * автоматическое сообщение о новых потоках * команду `thread THREADNO' для переключения среди потоков * команду `info threads' для запроса информации о существующих потоках * команду `thread apply [THREADNO] [ALL] ARGS' для применения некоторой команды к списку потоков * определенные для потоков точки останова Предупреждение: Эти средства доступны еще не на каждой конфигурации GDB, даже если операционная система поддерживает потоки. Если ваша версия GDB не поддерживает потоков, эти команды не имеют никакого смысла. Например, система без поддержки потока ничего не выводит на запрос `info threads' и всегда отклоняет команду `thread': (gdb) info threads (gdb) thread 1 - 34 - Thread ID 1 not known. Use the "info threads" command to see the IDs of currently known threads. Средства GDB для отладки потоков позволяют наблюдать за всеми потоками во время выполнения программы, но всегда, когда GDB берет управление, один поток выделяется отдельно. Его называют "текущим потоком". Команды отладчика выдают программе информацию о текущем потоке. Когда бы GDB ни обнаружил новый поток вашей прогаммы, он выводит идентификацию целевой системы для потока в виде сообщения вида `[New SYSTAG]'. SYSTAG - идентификатор потока, формат которого зависит от конкретной системы. Например, в LynxOS будет выведено сообщение: [New process 35 thread 27] когда GDB заметит новый поток. Напротив, в системе SGI, SYSTAG выглядит, подобно `process 368', без дальнейших спецификаций. В целях отладки, GDB присваивает каждому потоку вашей программы его собственный номер - целое число. `info threads' Вывести краткую информацию обо всех потоках вашей программы в текущий момент. GDB отображает для каждого потока информацию в следующем порядке: 1. номер потока, назначенный GDB 2. Идентификатор целевой системы для потока (SYSTAG) 3. Краткие сведения о текущей процедурной секции данного потока Звездочка `*' слева от номера потока указывает на текущий поток. - 35 - Например, (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 () Как и в сообщении о новом потоке `[New ...]', форма текста после слов `Switching to' зависит от идентификации потоков в вашей системе. `thread apply [THREADNO] [ALL] ARGS' Команда `thread apply' позволяет Вам применять команду к одному и более потокам. Определите номера потоков, на которые Вы хотите повлиять, с помощью командного параметра THREADNO. THREADNO - внутренний номер потока в GDB, выводимый в первом поле `info threads'. Если Вы хотите применить команду ко всем потокам, используйте `thread apply all' ARGS. Когда бы GDB ни остановил вашу программу - на точке останова или по сигналу, он автоматически отмечает поток, в котором возникло прерывание. GDB оповещает Вас о переключении на этот поток сообщением вида `[Switching to SYSTAG]'. Для получения большей информации о поведении GDB при остановке и повторном запуске многопотоковой программы, см.Раздел 5.4 [Остановка и - 36 - запуск многопотоковых программ]. Для получения информации о точках наблюдения в многопотоковых программах, см.Раздел 5.1.2 [Установка точек наблюдения]. 4.11. Отладка многопроцессных программ В GDB нет специальной поддержки для отладки программ, создающих дополнительные процессы с помощью функции `fork '. При ветвлении программы, GDB продолжает отладку основного процесса, а порожденнный процесс выполняется беспрепятственно. Если Вы установили точку останова в любом коде, который потом выполняется порожденным процессом, порожденный процесс получит сигнал `SIGTRAP', который прервет его (если только не будет перехвачен). Тем не менее, для отладки порожденного процесса не нужно выполнять трудоемких операций. Поместите обращение `sleep' в тексте, который выполняется после ответвления порожденного процесса. Эта операция полезна, только если установлена определенная системная переменная или если существует определенный файл, так, чтобы не возникла задержка, если Вы не захотите запустить GDB на порожденном процессе. Пока порожденный процесс бездействует, узнайте его идентификатор, используя программу `ps'. Затем присоедините GDB (при новом запуске GDB, если Вы отлаживаете и основной процесс тоже) к порожденному процессу (см.Раздел 4.7 [Присоединение]). С этого момента Вы можете отлаживать порожденный процесс, как любой присоединенный. - 37 - 5. Остановка и продолжение исполнения Основное применение отладчика - для остановки вашей программы до ее завершения, чтобы при обнаружении нарушений в работе вашей программы, Вы могли исследовать их и выяснить причину. Внутри GDB, ваша программа может остановиться по одной из нескольких причин: по сигналу, на точке останова, при достижении новой строки после команды `step' и т.п. Вы можете исследовать и изменить переменные, после чего продолжить выполнение. Обычно сообщения, выдаваемые GDB, содержат достаточно информации о состоянии вашей программы, но Вы можете в любое время явно запросить эту информацию. `info program' Вывести информацию о состоянии программы: запущена ли она, каким процессом, почему остановилась. 5.1. Точки останова, точки наблюдения и исключительные ситуации Точка останова останавливает вашу программу всякий раз при выполнении некоторого оператора в программе. Для каждой точки останова Вы можете добавить более тонкие условия останова вашей программы. Вы можете установить точку останова командой `break' или ее вариантами (см.Раздел 5.1.1 [Установка точки останова]), определяя место прерывания программы номером строки, именем функции или точным адресом в программе. На языках, обрабатывающих исключительные ситуации (подобных GNU C++), Вы можете установить точку останова при возникновении подобной ситуации (см.Раздел 5.1.3 [Точки останова и исключительные ситуации]). В конфигурациях SunOS 4.x, SVR4 и Alpha OSF/1 Вы можете устанавливать точки останова в общедоступных библиотеках до выполнения программы. Точка наблюдения - особая точка останова, останавливающая вашу программу при изменении значения какого-то выражения. Для установки точки наблюдения Вы должны воспользоваться особой командой (см.Раздел - 38 - 5.1.2 [Установка точек наблюдения]), но в остальном Вы можете управлять точкой наблюдения, как обычной точкой останова: подключение, отключение и удаление и тех, и других точек производится одними и теми же командами. Вы можете установить, должны ли выводиться значения из вашей программы автоматически всякий раз, когда GDB останавливается на точке останова. См.Раздел 8.6 [Автоматическое отображение]. При создании точки останова или точки наблюдения, GDB присваивает ей номер. Номера идут в последовательном порядке, начиная с единицы. Они используются в командах, управляющих различными особенностями точек останова, чтобы указать, какую точку Вы хотите изменить. Каждую точку останова можно подключить или отключить. Если Вы отключаете ее, она не будет никак воздействовать на вашу программу, пока Вы снова не подключите ее. 5.1.1. Установка точек останова Точки останова устанавливаются командой `break' (сокращенно `b'). В рабочей переменной отладчика `$bpnum' записывается номер последней установленной точки. Для получения информации о рабочих переменных, см.Раздел 8.9 [Рабочие переменные]. Вы можете задать точку останова несколькими способами. `break FUNCTION' Установить точку останова при входе в функцию FUNCTION. Если Вы используете язык, допускающий перегружение идентификаторов, такой, как C++, FUNCTION может относиться к более, чем одному возможному месту установки. Для получения информации о такой ситуации, см.Раздел 5.1.8 [Меню точек останова]. - 39 - `break +OFFSET' `break -OFFSET' Установить точку останова на какое-то число строк вперед или назад от исполняемой позиции в текущей процедурной секции. `break LINENUM' Установить точку останова на строке LINENUM в текущем исходном файле. Таким файлом считается последний файл, исходный текст которого печатался. Эта точка останавливает вашу программу при выполнении любого кода из данной строки. `break FILENAME:LINENUM' Установить точку останова на строке LINENUM в исходном файле FILENAME. `break FILENAME:FUNCTION' Установить точку останова на входе в функцию FUNCTION, находящуюся в файле FILENAME. Определение имени файла лишнее, за исключением тех ситуаций, когда в нескольких файлах содержатся одинаково названные функции. `break *ADDRESS' Установить точку останова на адресе ADDRESS. Вы можете использовать такой способ установки в тех частях вашей программы, для которых нет отладочной информации, или в исходных файлах. `break' Вызванная без параметров, команда `break' установит точку останова на следующей инструкции, которая будет выполняться в выбранной процедурной секции (см.Главу 6 [Исследование процедурного стека]). В любой внутренней выбранной секции ваша программа будет остановлена, как только управление вернется в эту секцию. Это действие похоже на команду `finish' во внутренней для выбранной процедурной секции, только `finish' не оставляет активной точку останова. Если Вы используете `break' без параметров во внутренней секции, GDB остановится при следующем достижении текущего расположения, что может быть полезно при изучении внутренних циклов. - 40 - При продолжении исполнения, GDB обычно игнорирует точки останова после одной инструкции на выполнение. Если бы не было этого правила, Вы бы не смогли миновать предыдущие точки останова, предварительно не отключив их. Это правило применяется независимо от того, существовала ли точка останова или нет, когда остановилась ваша программа. `break ... if COND' Установить точку останова с условием COND; каждый раз при достижении точки останова проверяется условие и остановка происходит, только если значение ненулевое, т.е. условие истинное. `...' заменяет один из возможных параметров, описанных выше (или их отсутствие), указывая место прерывания. Для получения большей информации об условиях на точке останова, см.Раздел 5.1.6 [Условия останова]. `tbreak ARGS' Установить точку останова, предназначенную для одноразового прерывания. ARGS - те же параметры, что и для команды `break', и точка останова устанавливается по тем же правилам, но она автоматически стирается сразу после того, как программа остановилась на ней. См.Раздел 5.1.5 [Отключение точек останова]. `hbreak ARGS' Установить точку останова, поддерживаемую аппаратными средствами. ARGS те же параметры, что и для команды `break', и точка останова устанавливается по тем же правилам, но она требует поддержки аппаратными средствами, которую осуществляют не все целевые аппаратные средства. Основная цель такой точки останова - отладка кода EPROM/ROM, так что Вы можете установить точку останова на какой-то инструкции, не изменяя ее. Вы можете пользоваться этой командой при формировании захвата, обеспечиваемом SPARClite DSU. DSU генерирует ловушки при обращении программы к некоторой дате или адресу инструкции, назначенному регистрами отладки. Однако регистры точки останова аппаратных средств могут принять только две точки останова, и GDB отклонит эту команду, если будут использоваться больше, чем две. В этом случае, сотрите или - 41 - отключите неиспользуемые точки аппаратных средств перед установкой новых. См.Раздел 5.1.6 [Условия останова]. `thbreak ARGS' Установить точку останова, поддерживаемую аппаратными средствами, предназначенную для одноразового прерывания. ARGS те же параметры, что и для команды `hbreak', и точка останова устанавливается по тем же правилам, однако, как и по команде `tbreak', она автоматически стирается сразу после того, как программа остановилась на ней. Также, подобно `hbreak', точка останова требует аппаратной поддержки, не всегда присутствующей в рабочей целевой среде. См.Раздел 5.1.5 [Отключение точек останова]. Также см.Раздел 5.1.6 [Условия останова]. `rbreak REGEX' Установить точки останова на всех функциях, соответствующих регулярному выражению REGEX. Эта команда устанавливает безусловную точку останова во всех соответствующих местах, выводя список всех установленных точек. После подобной установки, точки останова рассматриваются так же, как установленные командой `break'. Вы можете стирать их, отключать или делать их условными таким же образом, как и другие точки останова. При отладке программ C ++, `rbreak' используется для установки точек останова на перегруженных функциях, которые не являются элементами никакого специального класса. `info breakpoints [N]' `info break [N]' `info watchpoints [N]' Вывести таблицу всех установленных и не стертых точек останова и точек наблюдения, со следующими столбцами для каждой точки останова: Номер точки останова. Тип: точка останова или точка наблюдения. - 42 - Расположение: отмечена ли точка останова для отключения или удаления при достижении. Подключена или нет: подключенная точка отмечается `y'. Остальные точки отмечаются `n'. Адрес точки в вашей программе (адрес памяти). Место точки в исходном тексте вашей программы (файл и номер строки). Если точка останова условная, `info break' показывает условие на строке, следующей после условной точки; после этого перечисляются команды точки останова, если они есть. `info break', с номером точки останова N в качестве параметра, выводит информацию только об этой точке. Рабочая переменная `$_' и используемый по умолчанию адрес исследования для команды `x' устанавливается по адресу последней перечисленной точки останова (см.Раздел 8.5 [Исследование памяти]). В настоящее время, `info break' отображает число достижений точки останова. Эта информация полезна для использования в команде `ignore'. Вы можете игнорировать точку останова столько раз, сколько нужно, чтобы остановиться на ее последнем достижении. GDB позволяет Вам установить несколько точек останова на одном и том же месте. В этом есть определенный смысл, даже при использовании условных точек (см.Раздел 5.1.6 [Условия останова]). Иногда GDB для специальных целей, типа обработки `longjmp' в программах C, сам устанавливает в вашей программе точки останова. Этим внутренним точкам останова присваиваются отрицательные номера, начинающиеся с `-1'; `info break' их не выводит. Вы можете увидеть их с помощью команды GDB `maint info breakpoints'. - 43 - `maint info breakpoints' Отобразить как те точки, которые Вы установили явно, так и используемые GDB для внутренних целей, используя тот же формат, что и `info break'. Внутренние точки показаны отрицательными номерами. Тип точки влияет на формат колонки: `breakpoint' Нормальная, явно устанавленная точка останова. `watchpoint' Нормальная, явно устанавленная точка наблюдения. `longjmp' Внутренняя точка останова, используемая для обработки вызова `longjmp'. `longjmp resume' Внутренняя целевая точка останова `longjmp'. `until' Временная внутренняя точка останова, используемая командой GDB `until'. `finish' Временная внутренняя точка останова, используемая командой GDB `finish'. 5.1.2. Установка точек наблюдения Вы можете использовать точку наблюдения, чтобы остановить выполнение, как только изменится значение какого-либо выражения, не указывая конкретно место, где произойдет изменение. Точки наблюдения в настоящее время обрабатываются на два порядка медленнее, чем другие точки останова, но зато Вы можете отловить ошибку, даже когда не имеете ни малейшего представления о том, в какой части программы она находится. - 44 - `watch EXPR' Установить точку наблюдения для выражения. GDB прервет работу программы, когда EXPR поменяет значиние. Вы можете пользоваться этой командой при формировании захвата, обеспечиваемом SPARClite DSU. DSU генерирует ловушки при обращении программы к некоторой дате или адресу инструкции, назначенному регистрами отладки. Для адресов данных, DSU выполняет команду `watch'. Однако, регистры точки останова аппаратных средств могут принять только две точки наблюдения за данными, и обе должны быть одного типа. Например, Вы можете установить две точки наблюдения командой `watch, либо командой `rwatch', либо командой `awatch', но Вы не можете установить одну точку одной командой, а другую - другой. Если Вы попытаетесь смешать две точки, GBD отклонит команду сообщением {No Value For "GBDN"}. Сотрите или отключите неиспользующиесяся точки наблюдения перед подключением новых. `rwatch EXPR' Установить точку наблюдения, которая остановит программу при считывании наблюдаемых ARGS. Если Вы используете обе точки наблюдения, они должны быть установлены командой `rwatch'. `awatch EXPR' Установить точку наблюдения, которая остановит программу при считывании или записывании наблюдаемых ARGS. Если Вы используете обе точки наблюдения, они должны быть установлены командой `awatch'. `info watchpoints' Эта команда выводит список точек наблюдения и точек останова, аналогично команде `info break'. Предупреждение: в многопотоковых программах, точки наблюдения лишь снижают эффективность. При установке точки наблюдения, GDB может следить за значением выражения только в одном потоке. Если Вы уверены, что выражение может измениться только под влиянием текущего потока (и что никакой другой поток не станет текущим), Вы - 45 - можете пользоваться точкой наблюдения как обычно. Однако GDB не заметит изменения значения, если оно произойдет не в текущем потоке. 5.1.3. Точки останова и исключительные ситуации Некоторые языки, такие как GNU C++, выполняют обработку исключительных ситуаций. Вы можете с помощью GDB, исследовать причину возникновения исключительной ситуации в вашей программе и перечисить исключительные ситуации, подготовленные вашей программой для обработки в данный момент времени. `catch EXCEPTIONS' Вы можете установить точки останова при активной реакции программы на исключительную ситуацию командой `catch'. EXCEPTIONS - список выявляемых исключительных ситуаций. Вы можете воспользоваться `info catch', чтобы перечислить все исключительные ситуации, обрабатываемые программой. См.Раздел 6.4 [Информация о процедурной секции]. В настоящее время в GDB имеются некоторые ограничения к обработке исключительных ситуаций: * Если Вы вызываете функцию в интерактивном режиме, GDB обычно возвращает Вам управление при завершении функции. Если обращение приводит к возникновению исключительной ситуации, механизм вовращения управления может не сработать, что приведет к выполнению программы до точки останова, сигнал от которой воспринимается GDB, или до конца. * Вы не можете вызвать исключительную ситуацию в интерактивном режиме. * Вы не можете обрабатывать исключительную ситуацию в интерактивном режиме. Иногда `catch' - не лучший способ отладки обработки исключительных ситуаций: если Вам необходимо узнать точное место появления - 46 - исключительной ситуации, лучше остановить программу до вызова обработки исключительной ситуации,таким образом Вы можете увидеть процедурный стек до завершения любой операции. Иначе, если Вы установите особую точку при вызове обработки исключительной ситуации, Вам будет непросто выяснить точное место появления исключительной ситуации. Вам необходимы некоторые сведения о вызове обработки исключительной ситуации, чтобы остановиться точно перед ним. В случае GNU C++, исключительные ситуации возбуждаются вызовом библиотечной функции `__raise_exception', которая сопровождается сообщением ANSI C: /* ADDR is where the exception identifier is stored. ID is the exception identifier. */ void __raise_exception (void **ADDR, void *ID); Установите точку останова на `__raise_exception', чтобы отловить все исключительные ситуации до завершения любой стековой операции. См.Раздел 5.1 [Точки останова, точки наблюдения и исключительные ситуации]. С помощью условной точки останова (см.Раздел 5.1.6 [Условия останова]), зависящей от значения идентификатора ситуации, Вы можете остановить вашу программу при возникновении определенной исключительной ситуации. Вы можете использовать несколько условных точек останова, чтобы остановить вашу программу при возникновении одной из нескольких исключительных ситуаций. 5.1.4. Удаление точек останова Часто, когда Вы больше не хотите, чтобы программа останавливалась на точке останова или точке наблюдения, возникает необходимость в ее удалении. Удаленная точка забывается. Командой `clear' Вы можете удалять точки останова, согласно их расположению в вашей программе. Командой `delete' Вы можете удалять конкретную точку, указывая ее номер. - 47 - Нет необходимости удалять точку останова, чтобы миновать ее. GDB автоматически игнорирует точки после первой инструкции на выполнение, когда Вы продолжаете исполнение, не изменяя его адрес. `clear' Удаляет все точки останова на следующей инструкции в указанной процедурной секции (см.Раздел 6.3 [Выбор процедурной секции]). Эта команда - хороший способ удалить точку останова, на которой только что остановилась программа, если выбрана внутренняя секция. `clear FUNCTION' `clear FILENAME:FUNCTION' Удалить все точки останова при входе в FUNCTION. `clear LINENUM' `clear FILENAME:LINENUM' Удалить все точки останова, установленные на указанной строке или на кодах в ее пределах. `delete [breakpoints] [BNUMS...]' Удалить точки, номера которых заданы в качестве параметров. Если параметры не заданы, удалить все точки (если Вы не установили `set confirm off', GDB запрашивает подтверждение). Вы можете сократить эту команду как `d'. 5.1.5. Отключение точек останова Вместо удаления точки останова или точки наблюдения, Вы можете отключить ее. В этом случае она становится бездействующей, как если бы Вы ее удалили, но информация о ней сохраняется, так что Вы можете позже подключить ее снова. Вы можете, по желанию указывая в качестве параметра номера точек останова, отключать и подключать их командами `disable' и `enable'. Используйте команду `info break' или `info watch', для того чтобы - 48 - вывести список точек, если Вы не знаете нужные Вам номера. Точка останова или точка наблюдения может быть в одном из следующих четырех состояний: * Подключена. Точка останова останавливает вашу программу. Точки останова, установленные командой `break', находятся в этом состоянии. * Отключена. Точка останова не влияет на вашу программу. * Временно подключена. Точка останова останавливает вашу программу и отключается. В этом состоянии находятся точки останова, установленные командой `tbreak'. * Подключена для удаления. Точка останова останавливает вашу программу и немедленно удаляется. Для подключения или отключения точек останова и точек наблюдения Вы можете использовать следующие команды: `disable [breakpoints] [BNUMS...]' Отключить указанные точки останова - или все точки останова, если параметр отсутствует. Отключенная точка не влияет на программу, но все опции (количество проходов точки останова без выхода в отладчик, условия, команды и т.п.) сохраняются в случае нового подключения. Вы можете сокращать `disable' до `dis'. `enable [breakpoints] [BNUMS...]' Подключить указанные (или все) точки останова. Они опять влияют на остановку вашей программы. `enable [breakpoints] once BNUMS...' Временно подключить указанные точки останова. GDB отключает любую из этих точек сразу после остановки вашей программы на ней. `enable [breakpoints] delete BNUMS...' Подключить указанные точки останова для однократного срабатывания и последующего удаления. GDB удаляет любую из этих точек, как - 49 - только ваша программа остановится на ней. Исключая точки останова, установленные командой `tbreak' (см.Раздел 5.1.1 [Установка точек останова]), установленные Вами точки изначально подключены; Вы можете впоследствии отключать или подключать их только вышеперечисленными командами. (Команда `until' может установить и стереть собственную точку останова, не изменяя при этом состояния других ваших точек; см.Раздел 5.2 [Продолжение исполнения и пошаговое выполнение]). 5.1.6. Условия останова Обычные точки останова останавливают вашу программу всякий раз при достижении указанного места. Также вы можете определить "условие" для точки останова. Условие - это Булево выражение на языке вашей программы (см.Раздел 8.1 [Выражения]). Условная точка останова вычисляет выражение всякий раз, когда ваша программа достигает ее, и программа останавливается только если условие истинно. Условия для точек останова действуют обратно утверждениям для проверки правильности программы; во втором случае остановка производится, если уловие нарушено, т.е., когда условие ложно. В C, если Вы проверяете выражение, представленное условием ASSERT, Вы должны установить условие "! ASSERT" для соответствующей точки останова. Условия также принимаются и для точек наблюдения. Вы можете и не нуждаться в них, т.к. точка наблюдения в любом случае рассматривает значение какого-то выражения. Однако может быть проще просто установить точку останова на имени переменной и определить условие, определяющее, интересует ли Вас новое значение. У условных прерываний могут быть побочные эффекты, даже вызов функции из вашей программы. Этим можно пользоваться, например, для того, чтобы вызвать функцию, следящую за процессом программы, или для того, чтобы использовать вашу собственную функцию печати для форматирования специальных структур данных. Действия полностью - 50 - предсказуемы, если только нет другой подключенной точки останова с тем же адресом. (В этом случае GDB может заметить другую точку останова раньше и остановить вашу программу, не проверяя условия). Заметим, что, для выполнения побочных действий при достижении точки останова, команды точки останова более удобны и гибки, чем условия (см.Раздел 5.1.7 [Списки команд точек останова]). Условия прерываний могут быть определены при установке точки останова с помощью параметра `if' команды `break'. См.Раздел 5.1.1 [Установка точек останова]. Их можно изменить в любое время командой `condition'. Команда `watch' не распознает ключевое слово `if'; команда `condition' - единственный способ наложить условие на точку наблюдения. `condition BNUM EXPRESSION' Определить EXPRESSION как условие прерывания для точки останова или точки наблюдения под номером BNUM. После установки условия, Точка останова останавливает вашу программу, только если значение EXPRESSION истинно (в С - ненулевое). Когда Вы используете `condition', GDB немедленно проверяет синтаксическую правильность EXPRESSION и определяет, присутствуют ли используемые символы в контексте вашей точки останова. GDB, однако, не вычисляет EXPRESSION тогда, когда вы даете команду `condition'. См.Раздел 8.1 [Выражения]. `condition BNUM' Удалить условие из точки останова под номером BNUM. Она становиться обычной безусловной точкой останова. Особый тип условия точки останова - останавливаться только после достижения ее определенного числа раз. Он настолько полезен, что для его установки есть специальный способ - с помощью счетчика количества проходов точки останова без выхода в отладчик, который есть у каждой точки останова и значение которого - целочисленное. Большую часть времени количество проходов точки останова без выхода в отладчик равно нулю и счетчик не задействован. Но если ваша программа достигает точку останова, значение счетчика которой положительно, она не останавливается, а лишь уменьшает его значение на единицу и продолжает - 51 - выполняться. В результате, если установить значение счетчика на N, точка останова не будет останавливать вашу программу при N следующих ее достижениях. `ignore BNUM COUNT' Установить счетчик точки останова под номером BNUM на COUNT. В следующие COUNT раз достижения точки останова, выполнение вашей программы не прервется; GDB не произведет никаких действий, кроме уменьшения значения счетчика. Для того чтобы остановиться на точке останова при следующем достижении, установите счетчик на ноль. Когда Вы используете `continue' для продолжения выполнения вашей программы от точки останова, Вы можете определить значение счетчика непосредственно как параметр `continue', вместо того, чтобы использовать `ignore'. См.Раздел 5.2. [Продолжение исполнения и пошаговое выполнение]. Если в точке останова установлено положительное значение счетчика и есть условие, то это условие не проверяется. Только при обращении счетчика в ноль, GDB проверяет условие. Вы можете сгенерировать действие счетчика с помощью условия типа `$foo-- <= 0', использующего рабочие переменные отладчика, которые каждый раз уменьшаются. См.Раздел 8.9 [Рабочие переменные]. 5.1.7. Списки команд точек останова Вы можете задать любой точке останова (или точке наблюдения) ряд команд, которые будут выполняться при остановке программы на этой точке останова. Например, Вы можете пожелать вывести значения определенных выражений или подключить другие точки останова. - 52 - `commands [BNUM]' `... COMMAND-LIST ...' `end' Определить список команд для точки останова под номером BNUM. Команды пишутся на последующих строках. Наберите строку, содержащую `end', чтобы закончить список. Чтобы удалить все команды из точки останова, наберите `commands' и сразу же - `end'; т.е., задайте пустой список команд. Если нет параметра BNUM, `commands' относится к последней установленной (но не последней встретившейся) точке останова или точке наблюдения. Внутри COMMAND-LIST нажатие RET не воспринимается как повтор команды GDB. Вы можете использовать команды точки останова, чтобы снова запустить вашу программу. Просто используйте команду `continue' или `step', или любую другую, продолжающую выполнение. Любая команда в списке, стоящая после команды, которая продолжает выполнение, игнорируется. Это сделано, потому что при продолжении выполнения (даже простыми `next' и `step') Вы можете встретить другую точку останова, у которой может быть свой собственный список команд, что приведет к неопределенности, какой список выполнять. Если первой командой в списке Вы укажете `silent', то обычное сообщение об остановке на точке останова не выведется. Его отсутствие может быть желательно на точках останова, выводящих специальное сообщение и продолжающих выполнение. Если ни одна из остальных команд ничего не выводит, Вы не увидите никакого признака достижения этой точки останова. `silent' имеет смысл только в начале списка команд. Команды `echo', `output' и `printf' позволяют Вам управлять выводом, они полезны для фоновых точек останова. См.Раздел 15.4 [Команды управления выводом]. - 53 - В данном примере показано, как Вы можете использовать команды точки останова при входе в `foo' при условии, что `x' положительно, для вывода значения `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 5.1.8. Меню точек останова Некоторые языки программирования (особенно C++) допускают "перегружение" имени функции - определение этого имени несколько раз, для применения в различных контекстах. Если имя функции перегруженно, команды `break FUNCTION' недостаточно, чтобы сообщить GDB о желаемом месте установки точки останова. Вы можете набрать что-нибудь типа `break FUNCTION(TYPES)', чтобы конкретизировать, какой вариант функции Вам нужен. Иначе GDB предложит Вам нумерованное меню возможных точек останова и выведет `>', дожидаясь Вашего выбора. Первые две опции - 54 - всегда `[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) 5.2. Продолжение исполнения и пошаговое выполнение "Продолжение исполнения" подразумевает продолжение исполнения вашей программы до ее нормального завершения. Напротив, "пошаговое выполнение" подразумевает выполнение только одного "шага" программы, под "шагом" понимается либо одна строка исходного текста, либо одна машинная инструкция (в зависимости от используемой Вами команды). При продолжении исполнения или пошаговом выполнении остановка вашей программы может произойти раньше - на точке останова или по сигналу. (Если остановка происходит по сигналу, Вы можете использовать `handle' или `signal 0', чтобы продолжить исполнение программы. См.Раздел 5.3 - 55 - [Сигналы]). `continue [IGNORE-COUNT]' `c [IGNORE-COUNT]' `fg [IGNORE-COUNT]' Продолжить выполнение программы с адреса последней остановки вашей программы; любые точки останова, установленные на этом адресе, игнорируются. Возможный параметр IGNORE-COUNT позволяет Вам указать, сколько раз должна игнорироваться точка останова на этом месте; он действует подобно параметру команды `ignore' (см.Раздел 5.1.6 [Условия останова]). Параметр IGNORE-COUNT имеет смысл только когда ваша программа остановилась на точке останова. В другом случае параметр команды `continue' будет игнорироваться. Синонимы `c' и `fg' введены для удобства и ведут себя точно так же, как `continue'. Если Вы хотите продолжить выполнение с другого места, Вы можете воспользоваться командой `return' (см.Раздел 11.4 [Возврат из фукции]), чтобы вернуться из вызванной фукции; или `jump' (см.Раздел 11.2 [Продолжение выполнения с другого адреса]), чтобы перейти к произвольному месту вашей программы. Типичная методика для использования пошагового выполнения состоит в следующем: установить точку останова (см.Раздел 5.1 [Точки останова, точки наблюдения и исключительные ситуации]) в начале функции или раздела вашей программы, где предположительно содержится ошибка; выполнять вашу программу до остановки на этой точке останова; затем производить пошаговое выполнение в подозрительной области, проверяя интересующие Вас переменные, до обнаружения ошибки. `step' Продолжить выполнение вашей программы до достижения управлением другой строки, затем остановить ее и передать управление GDB. Эта команда сокращается до `s'. - 56 - Предупреждение: Если Вы используете команду `step', находясь внутри функции, откомпилированной без отладочной информации, выполнение продолжается до тех пор, пока управление не достигнет функции, имеющей отладочную информацию. Аналогично, Вы не можете войти в функцию, откомпилированную без отладочной информации. Чтобы войти в такую функцию, используйте команду `stepi', описанную ниже. В этой версии команда `step' останавливает выполнение только на первой инструкции строки исходного текста. Таким образом предотвращаются многократные остановки, которые обычно происходят на утверждениях переключателя, в циклах и т.п. `step' по-прежнему останавливает выполнение, если внутри строки вызывается функция, имеющая отладочную информацию. Также, в этой версии, команда `step' входит в подпрограмму, только если имеется информация о номере строки этой подпрограммы. Иначе она действует подобно команде `next'. Таким образом избегаются проблемы при использовании `cc -gl' на MIPS машинах. Раньше, если была хоть какая-нибудь отладочная информация о программе, `step' входил в подпрограмму. `step COUNT' Продолжать выполнение, как по команде `step', но COUNT раз. Если во время COUNT шагов, встречается точка останова или возникает сигнал, не связанный с пошаговым выполнением, сразу происходит остановка. `next [COUNT]' Продолжать до следующей строки исходного текста в текущей процедурной секции. Эта команда действует, подобно `step', но не останавливается на функциях, вызываемых внутри строки программы. Выполнение останавливается, когда управление достигает другой строки на том процедурном уровне, который выполнялся, когда Вы дали команду `next'. Эта команда сокращается до `n'. Параметр COUNT указывает число повторений, как для команды `step'. - 57 - В этой версяя команда `next' останавливается только на первой инструкции строки исходного текста. Таким образом предотвращаются многократные остановки, которые обычно происходят на утверждениях переключателя, в циклах и т.п. `finish' Продолжать выполнение до выхода из функции в выбранной процедурной секции. Вывести возвращенное значение (если оно есть). Противопоставляется команде `return' (см.Раздел 11.4 [Возврат из функции]). `u' `until' Продолжать выполнение до тех пор, пока не будет достигнута строка исходного текста текущей процедурной секции, находящаяся после текущей строки. Эта команда предотвращает прохождение через цикл больше, чем один раз. Она действует, подобно команде `next', но, когда она встречается с переходом, она автоматически продолжает выполнение до тех пор, пока счетчик команд не станет больше, чем адрес перехода. Имеется ввиду, что, когда Вы, после однократного прохождения, достигаете конца цикла, `until' продолжает выполнение вашей программы до выхода из цикла. Напротив, команда `next' в конце цикла возвращает управление на начало цикла, вынуждая Вас повторить выполнение цикла. `until' всегда останавливает вашу программу при выходе из текущей процедурной секции. `until' может привести к несколько неожиданным результатам, если порядок машинных кодов не соответствует порядку строк исходного текста. В следующем примере, команда `f' (`frame') показывает, что выполнение прервано на строке 206; однако, когда мы пользуемся командой `until', мы получаем строку 195: - 58 - (gdb) f #0 main (argc=4, argv=0xf7fffae8) at m4.c:206 206 expand_input(); (gdb) until 195 for ( ; argc > 0; NEXTARG) { Это происходит, потому что, для большей эффективности, компилятор сгенерировал код для тестирования завершения цикла в конце цикла, а не в его начале; даже в C для оператора цикла `for' условие записывается перед телом цикла. Кажется, что команда `until' двигалась назад к началу цикла для продвижения до этого выражения; однако, в терминах фактического машинного кода это не так. Без параметров, `until' пошагово выполняет одиночные инструкции, и, следовательно, работает медленнее, чем `until' с параметром. `until LOCATION' `u LOCATION' Продолжить выполнение вашей программы либо до выхода из текущей процедурной секции, либо до достижения LOCATION. LOCATION - одна из форм допустимого параметра для команды `break' (см.Раздел 5.1.1 [Установка точек останова]). Эта форма команды использует точки останова, и поэтому работает быстрее, чем `until' без параметров. `stepi' `si' Выполнить одну машинную инструкцию, затем остановиться и вернуть управление отладчику. При пошаговом выполнении машинных инструкций, часто полезно использовать команду `display/i $pc'. Тогда всякий раз при остановке программы, GDB будет автоматически выводить следующую инструкцию к выполнению. См.Раздел 8.6 [Автоматическое отображение]. - 59 - Параметр COUNT указывает число повторений, как в команде `step'. `nexti' `ni' Выполнить одну машинную инструкцию, но если при этом вызывается какая-либо функция, продолжать выполнение до выхода из нее. Параметр COUNT указывает число повторений, как в команде `next'. 5.3. Сигналы Сигнал - асинхронное событие, которое может случиться в программе. Операционная система определяет возможные типы сигналов и дает каждому типу имя и номер. В Unix, например, `SIGINT' - сигнал, получаемый программой, когда Вы набираете символ прерывания (часто `C-c'); `SIGSEGV' - сигнал, получаемый программой при ссылке на область памяти, отличную от всех используемых областей; `SIGALRM' имеет место при срабатывании интервального таймера (возникает только, если ваша программа запросила временной сигнал). Некоторые сигналы, включая " SIGALRM ", являются нормальной частью функционирования вашей программы. Другие, типа " SIGSEGV ", указывают на ошибки; эти сигналы "фатальны" (уничтожают вашу программу немедленно), если в программе не определен заранее другой способ обработки сигнала. " SIGINT " не указывает на ошибку в вашей программе, но обычно является фатальным, так что он может выполнять функцию прерывания: уничтожать программу. GDB способен обнаружить любое местонахождение сигнала в вашей программе. Вы можете заранее сообщить GDB, что делать для каждого типа сигнала. В обычном состоянии GDB игнорирует неаварийные сигналы, подобные `SIGALRM' (чтобы не сталкиваться с их действием на исполнение вашей программы), но останавливает вашу программу всякий раз, когда возникает аварийный сигнал. Вы можете изменить эти установки командой `handle'. - 60 - `info signals' Вывести таблицу всех типов сигналов и описания их обработки GDB. Вы можете использовать эту команду, чтобы узнать номера всех определенных типов сигналов. `info handle' - новое имя для `info signals'. `handle SIGNAL KEYWORDS...' Изменить способ обработки GDB сигнала SIGNAL. SIGNAL может быть номером сигнала или его именем (и иметь или не иметь `SIG' в начале). KEYWORDS сообщают, какие совершить изменения. Ключевые слова, допустимые командой `handle', можно сокращать. Их полные имена: `nostop' GDB не должен останавливать вашу программу при получении описываемого сигнала. Все же может выводиться сообщение о получении этого сигнала. `stop' GDB должен остановить вашу программу при получении описываемого сигнала. При этом подразумевается ключевое слово `print'. `print' GDB должен вывести сообщение о получении сигнала. `noprint' GDB вообще не должен реагировать на сигнал. При этом подразумевается ключевое слово `nostop'. `pass' GDB разрешает вашей программе реагировать на сигнал; ваша программа может обрабатывать сигнал или же может завершиться, если сигнал фатален и не обрабатывается. - 61 - `nopass' GDB запрещает вашей программе реагировать на сигнал. Когда сигнал останавливает вашу программу, его нельзя заметить, пока Вы не продолжите выполнение. Тогда ваша программа реагирует на сигнал, если на него распространяется действие команды `pass' *в данное время*. Другими словами, после сообщения GDB о сигнале, Вы можете воспользоваться командой `handle' c ключевыми словами `pass' или `nopass', чтобы указать, реагировать ли вашей программе на этот сигнал при продолжении. Вы также можете использовать команду `signal' для того, чтобы ваша команда пропустила или, наоборот, заметила обычно игнорируемый сигнал. Например, если ваша программа остановилась из-за ошибки обращения к памяти, Вы можете установить правильное значение в ошибочной переменной и продолжить исполнение, в надежде на дальнейшую правильность; но, скорее всего, ваша программа остановилась бы из-за фатального сигнала, если бы заметила его. Чтобы предотвратить остановку, Вы можете продолжать исполнение с установкой `signal 0'. См.Раздел 11.3 [Подача сигнала вашей программе]. 5.4. Остановка и запуск многопотоковых программ Когда у вашей программы есть несколько потоков выполнения (см.Раздел 4.10 [Отладка программ с несколькими потоками]), Вы можете по желанию устанавить точки останова либо на всех, либо на каких-то конкретных потоках. `break LINESPEC thread THREADNO' `break LINESPEC thread THREADNO if ...' LINESPEC определяет строки исходного текста, всегда лучше указывать одну строку исходного текста. Используйте спецификатор `thread THREADNO' с командой точки останова, чтобы конкретизировать поток, при достижении которым этой точки останова GDB должен остановить программу. THREADNO - номер потока, назначенный GDB, указываемый в первом столбце вывода команды `info threads'. - 62 - Если при установке точки останова, Вы не определили `thread THREADNO', точка останова будет отнесена ко всем потокам вашей программы. Также Вы можете использовать спецификатор `thread' на условных точках останова; в этом случае, поместите `thread THREADNO' перед условием. Пример: (gdb) break frik.c:13 thread 28 if bartab > lim При любой остановке вашей программы под управлением GDB, прекращается выполнение всех (а не только текущего) потоков. Т.о., Вы можете исследовать полное состояние программы, вплоть до использования переключения между потоками, не опасаясь что-либо изменить. И обратно, когда бы Вы ни запустили программу, начинают выполняться все потоки. Это верно и при пошаговом выполнении командами, подобными `step' или `next'. В частности, GDB не может жестко управлять всеми потоками. Так как планирование потока предоставлено операционной системе целевой машины (не управляемой GDB), то, пока в текущем потоке совершается один шаг, в других потоках может выполниться более одного оператора. Более того, когда выполнение программы прерывается, другие потоки останавливаются в середине каких-то операторов чаще, чем на границе между ними. Вы можете обнаружить, что после продолжения исполнения или даже после пошагового выполнения, ваша программа остановилась на другом потоке. Это случается, когда другой поток достигает точку останова, получает сигнал или в нем возникает исключительная ситуация прежде, чем первый поток завершит выполнение требуемых Вами действий. - 63 - 6. Исследование процедурного стека При остановке вашей программы, первое, что Вам нужно знать,- это где и почему она остановилась. Каждый раз при вызове вашей программой какой-либо функции, генерируется информация об этом вызове, включающая в себя место вызова, параметры вызова и локальные переменные вызванной функции. Эта информация сохраняется в блоке данных, называемом "процедурной секцией". Процедурные секции размещаются в области памяти, называемой "стеком вызовов". Команды GDB для исследования стека позволяют Вам ознакомиться со всей этой информацией при остановке вашей программы. GDB выбирает одну из процедурных секций, и часть команд GDB неявно обращается к ней. В частности, при запросе у GDB значения переменной из вашей программы, это значение ищется в выбранной секции. Существуют специальные команды GDB для выбора интересующей Вас секции. См.Раздел 6.3 [Выбор процедурной секции]. При остановке вашей программы, GDB автоматически выбирает текущую исполняемую секцию и выдает ее краткое описание, как команда `frame' (см.Раздел 6.4 [Информация о процедурной секции]). 6.1. Процедурные секции Cтек вызовов разделен на непрерывные фрагменты, называемые "процедурными секциями" или "секциями" ("фреймами") для краткости; каждая секция содержит данные, связанные с одним вызовом одной функции: аргументы функции, ее локальные переменные и адрес, с которого она выполняется. При запуске программы, стек содержит только одну секцию - для функции `main'. Она называется начальной или внешней секцией. Каждый раз при вызове функции создается новая процедурная секция. При выходе из функции, секция этого функционального вызова удаляется. Для - 64 - рекурсивной функции может быть создано несколько секций. Процедурная секция функции, исполняемой в данный момент, называется внутренней (она создана позже всех остальных секций). Процедурные секции внутри вашей программы идентифицируются своими адресами. Секция состоит из нескольких байтов, каждый из которых имеет свой собственный адрес; у каждого типа компьютера есть свой способ нахождения байта, адрес которого служит адресом секции; обычно, пока выполнение относится к данной секции, адрес этого байта содержится в регистре указателя секции. Всем существующим процедурным секциям GDB присваивает номера; нулевой номер присваивается внутренней секции, первый - следующей за ней и т.д. В вашей программе эти номера не имеют смысла; GDB назначает их для обозначения процедурных секций в командах GDB. Некоторые компиляторы позволяют компилировать функции так, чтобы они выполнялись без использования процедурных секций. (Например, `gcc' обеспечивает это опцией `-fomit-frame-pointer'). Такая компиляция удобна при обращении вашей программы к часто используемым библиотечным функциям, чтобы не тратить время на установку процедурных секций. GDB ограничен в средствах обработки таких функциональных вызовов. Если вызов внутренней функции происходит без использования процедурной секции, GDB, тем не менее, описывает его как отдельную секцию под номером ноль, позволяя должным образом отслеживать цепочку функциональных вызовов. Однако GDB не имеет никаких средств для работы с такими функциями вне стека. `frame ARGS' Команда `frame' позволяет переходить от одной процедурной секции к другой и выводит выбранную Вами секцию. ARGS может быть либо адресом секции, либо номером процедурной секции. `frame' без параметров выводит текущую процедурную секцию. `select-frame' Команда `select-frame' позволяет Вам переходить от одной секции к другой, без вывода секции. Это "молчаливая" версия `frame'. - 65 - 6.2. Цепочки вызовов Цепочка вызовов предоставляет информацию о последовательности вызовов подпрограмм, которая привела к данной точке программы. Эта информация содержит по одной строке на каждую процедурную секцию, начиная с текущей (секции ноль), вверх по стеку. `backtrace' `bt' Вывести цепочку вызовов всего стека: по одной строке на секцию для всех процедурных секций стека. Вы можете прервать отслеживание в любое время вызовом системного прерывания, обычно `C-c'. `backtrace N' `bt N' То же самое, но выводятся только N внутренних секций. `backtrace -N' `bt -N' То же самое, но выводятся только N внешних секций. `where' и `info stack' (сокращенно `info s') - синонимы `backtrace'. Каждая строка цепочки вызовов содержит номер секции и имя функции. Счетчик команд (PC) показывается, если только Вы не использовали команду `set print address off'. Также цепочка вызовов показывает имя исходного файла, номер строки и аргументы функции. Значение PC опускается, если PC указывает на начало кода строки. Ниже приведен пример цепочки вызовов. Используется команда `bt 3' для вывода информации о трех внутренних секциях. #0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8) at builtin.c:993 - 66 - #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...) Информация о секции ноль не содержит значения PC, что указывает на то, что ваша программа остановилась в начале строки `993' файла `builtin.c'. 6.3. Выбор процедурной секции Большинство команд для исследования стека и других данных в вашей программе применяются к любой выбранной секции. Здесь приведены команды для выбора процедурной секции; все они завершаются выводом краткого описания выбранной процедурной секции. `frame N' `f N' Выбрать секцию под номером N. Считается, что нулевая секция - внутренняя (исполняемая в текущее время), первая - та, из которой вызвана нулевая и т.д. Секция с наибольшим номером - процедурная секция функции `main'. `frame ADDR' `f ADDR' Выбрать секцию по адресу ADDR. Обычно используется, если формирование цепочки процедурных секций было нарушено какой-либо ошибкой, что привело к невозможности должным образом присвоить номера всем секциям. Кроме того, эта команда может быть полезна, когда у вашей программы есть несколько процедурных стеков и она переходит от одного к другому. В архитектуре SPARC, команде `frame' для выбора произвольной процедурной секции необходимо задать два адреса: указатель секции и указатель вершины стека. В архитектурах MIPS и Alpha также требуется два адреса: указатель - 67 - вершины стека и PC. В архитектуре 29k требуется три адреса: указатель вершины регистрового стека, PC и указатель вершины стека в памяти. `up N' Передвинуться вверх по стеку. Для положительных N это продвижение происходит по направлению к внешней процедурной секции; по возрастанию номеров секций; к секциям, образованным раньше. По умолчанию N равно единице. `down N' Передвинуться вниз по стеку. Для положительных N это продвижение происходит по направлению к внутренней процедурной секции; по убыванию номеров секций; к секциям, образованным позже. По умолчанию N равно единице. Вы можете сокращать `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' без параметров выведет десять строк, расположенных вокруг точки выполнения в секции. См.Раздел 7.1 [Вывод строк исходного текста]. - 68 - `up-silently N' `down-silently N' Эти две команды являются вариантами `up' и `down' соответственно, отличаясь от них "молчаливой" работой, т.е. не отображают новую секцию. Прежде всего они предназначены для использования в пакетных файлах GDB, когда вывод может быть ненужным и отвлекающим. 6.4. Информация о процедурной секции Существуют и другие команды для вывода информации о выбранной процедурной секции. `frame' `f' При использовании этой команды без параметров, выбор новой секции не происходит, но выводится краткое описание уже выбранной секции. Сокращение команды - `f'. С параметром эта команда используется для выбора процедурной секции. См.Раздел 6.3 [Выбор процедурной секции]. `info frame' `info f' Эта команда выводит подробное описание выбранной процедурной секции, включающее в себя: * Адрес процедурной секции * Адрес следующей вниз по стеку процедурной секции (вызываемой из данной) * Адрес следующей вверх по стеку процедурной секции (вызывающей данную) * Язык, на котором написан соответствующий этой секции исходный текст * Адрес аргументов процедурной секции - 69 - * Сохраненный в секции PC (адрес выполнения в секции, вызвавшей данную) * Регистры, которые были сохранены в секции Подробное описание полезно, если из-за какой-то ошибки формат стека не соответствует обычным соглашениям. `info frame ADDR' `info f ADDR' Вывести подробное описание процедурной секции по адресу ADDR, не выбирая этот заново процедурную секцию. Эта команда не выбирает новую секцию. Она требует параметр ADDR (для некоторых архитектур больше, чем один) того же типа, что и команда `frame'. См.Раздел 6.3 [Выбор процедурной секции]. `info args' Вывести на отдельных строках аргументы выбранной процедурной секции. `info locals' Вывести на отдельных строках локальные переменные выбранной процедурной секции. Выводятся все переменные, объявленные как статические или локальные динамические и доступные в точке выполнения выбранной процедурной секции. `info catch' Вывести перечень всех типов обработки исключительных ситуаций, действительных в текущей точке выполнения текущей процедурной секции. Для того, чтобы увидеть другие типы обработок исключительных ситуаций, перейдите в соответствующую секцию, используя команды `up', `down' или `frame'; затем наберите `info catch'. См.Раздел 5.1.3 [Точки останова и исключительные ситуации]. - 70 - 6.5. MIPS машины и функциональный стек MIPS машины используют нестандартный формат процедурных секций, который для поиска начала функции иногда заставляет GDB идти назад по объектному коду. Для уменьшения времени реакции (особенно для вложенных приложений, когда GDB может быть ограничен медленной линией последовательного поиска), Вы можете ограничить размер этого поиска с помощью одной из следующих команд: `set heuristic-fence-post LIMIT' Запретить GDB просматривать больше, чем LIMIT байтов при поиске начала функции. Значение 0 (устанавливаемое по умолчанию) означает отсутствие ограничений. Чем меньше предел (за исключением 0), тем меньше времени требуется на выполнение, т.к. просматривается меньшее число байтов. `show heuristic-fence-post' Отобразить текущий предел поиска. Эти команды допустимы только когда GDB сконфигурирован для отладки на MIPS процессорах. 7. Исследование исходных файлов GDB может выводить части источника вашей программы, так как отладочная информация, записанная в ней, сообщает GDB, какие исходные файлы использовались при создании программы. При остановке вашей программы, GDB сразу выводит строку, на которой произошла остановка. Аналогично, когда Вы выбираете процедурную секцию (см.Раздел 6.3 [Выбор процедурной секции]), GDB выводит строку, на которой остановилось выполнение в этой секции. Вы можете выводить другие части исходных файлов с помощью конкретных команд. Если Вы используете GDB в интерфейсе GNU Emacs, Вы можете воспользоваться средствами Emacs для просмотра исходных файлов; - 71 - см.Главу 16 [Использование GDB под управлением GNU Emacs]. 7.1. Вывод строк исходного текста Чтобы вывести строки исходного файла, используйте команду `list' (сокращенно `l'). По умолчанию выводится десять строк. Существует несколько способов для определения того, какую часть файла Вы хотите вывести. Здесь представлены наиболее употребительные формы команды `list': `list LINENUM' Из текущего исходного файла вывести строки, расположенные вокруг строки под номером LINENUM. `list FUNCTION' Вывести строки, расположенные вокруг начала функции FUNCTION. `list' Вывести определенное количество строк. Если последние выведенные строки выводились с помощью команды `list', то тогда выводятся строки, следующие за последними выведенными; однако, если последней выведенной строкой была одиночная строка, выведенная, как часть отображения процедурной секции стека (см.Главу 6 [Исследование процедурного стека]), то выводятся строки, расположенные вокруг нее. `list -' Вывести строки, непросредственно предшествующие последним выведенным. По умолчанию, для любой из этих форм команды `list' GDB выводит десять строк исходного текста. Вы можете поменять их количество командой `set listsize': `set listsize COUNT' Установить количество выводимых строк командой `list' числом - 72 - COUNT (если только параметр `list' не задаст их количество в явном виде). `show listsize' Отобразить количество строк, выводимых командой `list'. Повтор команды `list' нажатием RET сбрасывает параметр, так что повторение эквивалентно простому набору `list'. Это полезнее вывода тех же самых строк заново. Исключение сделано для параметра `-'; этот параметр сохраняется при повторе команды, так что происходит движение вверх по исходному файлу. Обычно для команды `list' от Вас ожидается ноль, один или два параметра "linespecs". Параметры "linespecs" определяют строки исходного текста; их можно записать несколькими способами, но эффективнее всегда указывать одну строку исходного текста. Здесь приводится полное описание возможных параметров команды `list'. `list LINESPEC' Вывести строки, расположенные вокруг строки, определенной LINESPEC. `list FIRST,LAST' Вывести строки от FIRST до LAST. Оба параметра - "linespecs". `list ,LAST' Вывести строки перед LAST. `list FIRST,' Вывести строки, начиная с FIRST. `list +' Вывести строки, идущие сразу за последними выведенными. `list -' Вывести строки, непосредственно предшествующие последним выведенным. - 73 - `list' См.выше. Ниже перечислены способы спецификации одиночной строки исходного текста - все типы "linespec". `NUMBER' Указывает на строку NUMBER из текущего исходного файла. Если у команды `list' есть два параметра "linespecs", NUMBER ссылается на тот же исходный файл, что и первый "linespec". `+OFFSET' Указывает на строку, смещенную вперед на OFFSET строк относительно последних выведенных. Когда используется в качестве второго параметра, указывает на смещение относительно строки, определенную первым "linespec". `-OFFSET' Указывает на строку, смещенную назад на OFFSET строк относительно последних выведенных. `FILENAME:NUMBER' Указывает на строку NUMBER из исходного файла FILENAME. `FUNCTION' Указывает на строку, с которой начинается тело функции FUNCTION. Например, в C оно начинается со строки с открывающей фигурной скобкой. `FILENAME:FUNCTION' Указывает на строку, с которой начинается тело функции FUNCTION в файле FILENAME. Имя файла необходимо указывать, только чтобы избежать неоднозначности, если в различных исходных файлах есть одинаково названные функции. `*ADDRESS' Указывает на строку, соответветствующую адресу программы ADDRESS. ADDRESS может быть любым выражением. - 74 - 7.2. Поиск в исходных файлах Существуют две команды для поиска регулярного выражения в текущем исходном файле. `forward-search REGEXP' `search REGEXP' Команда `forward-search REGEXP' проверяет на соответствие выражению REGEXP каждую строку, начиная со следующей за последней выведенной. Найденная строка выводится. Вы можете использовать синоним `search REGEXP' или сокращение `fo'. `reverse-search REGEXP' Команда `forward-search REGEXP', двигаясь назад, проверяет на соответствие выражению REGEXP каждую строку, начиная со строки, предшествующей последней выведенной. Найденная строка выводится. Возможное сокращение - `rev'. 7.3. Определение каталогов с исходными текстами Иногда исполняемые программы записывают имена исходных файлов, из которых они скомпилированы, без каталогов. Даже если они записывают пути, те могут измениться в период между компиляцией и сеансом отладки. У GDB есть список каталогов для поиска исходных файлов. Он называется путем поиска файлов с исходными текстами. Когда GDB ищет исходный файл, он по порядку перебирает все каталоги из этого списка, пока не находит желаемый файл. Заметим, что для этой цели не используются пути поиска исполняемых файлов, как и текущий рабочий каталог, если только он не записан в пути поиска файлов с исходными текстами. Если GDB не может найти исходный файл, используя путь поиска файлов с исходными текстами, а в объектной программе записан какой-то каталог, GDB просматривает и его. В последнюю очередь, если только путь поиска файлов с исходными текстами пуст и нет никакой записи о - 75 - каталоге компиляции, GDB просматривает текущий каталог. При переустановке или переупорядочивании пути поиска файлов с исходными текстами, GDB очищает любую сохраненную информацию о том, где находится исходный файл и о месторасположении строк в нем. Когда Вы запускаете GDB, путь поиска файлов с исходными текстами пуст. Для добавления каталогов используйте команду `directory'. `directory DIRNAME ...' `dir DIRNAME ...' Добавить каталог DIRNAME в начало пути поиска файлов с исходными текстами. Если в команде задаются несколько имен, они разделяются `:' или пробелом. Вы можете указать каталог, который уже есть в пути поиска файлов с исходными текстами; команда переместит его в начало, так что GDB сначала будет искать в нем. Вы можете использовать строку `$cdir' для ссылки на каталог компиляции (если он записан), а `$cwd' - для ссылки на текущий рабочий каталог. `$cwd' отличается от `.'. Первая отслеживает изменения текущего каталога во время сеанса работы GDB, тогда как вторая сразу расширяется до текущего каталога во время его добавления в путь поиска файлов с исходными текстами. `directory' Очистить путь поиска файлов с исходными текстами. Эта команда требует подтверждения. `show directories' Вывести путь поиска файлов с исходными текстами: показать, какие каталоги он содержит. Если путь поиска файлов с исходными текстами содержит уже неиспользуемые каталоги, GDB может найти неправильный вариант источника. Вы можете исправить ситуацию следующим образом: 1. Воспользоваться `directory' без параметров, чтобы очистить путь поиска файлов с исходными текстами. - 76 - 2. Использовать `directory' с подходящими параметрами, чтобы переустановить каталоги пути поиска файлов с исходными текстами. Вы можете добавить все желаемые каталоги одной командой. 7.4. Исходный текст и машинный код Вы можете использовать команду `info line', чтобы отобразить cтроки исходного текста, соответствующие программным адресам (и наоборот), и команду `disassemble', чтобы отобразить диапазон адресов в виде машинных инструкций. В этой версии отладчика, при работе под GNU Emacs, команда `info line' выводит стрелку для указания на определенную строку. `info line' выводит адреса как в шестнадцатеричной, так и в символьной форме записи. `info line LINESPEC' Вывести для строки исходного текста LINESPEC начальный и конечный адреса откомпилированной программы. Вы можете определить строку исходного текста любым из способов, описанных для команды `list' (см.Раздел 7.1 [Вывод строк исходного текста]). Например, мы можем использовать `info line' для получения местонахождения объектного кода первой строки функции `m4_changequote': (gdb) info line m4_changecom Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350. Также мы можем запросить (используя `*ADDR' как форму записи LINESPEC) информацмю об строке исходного текста, соответствующей конкретному адресу: (gdb) info line *0x63ff Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404. После `info line', адрес, используемый по умолчанию командой `x' меняется на начальный адрес строки, так что `x/i' достаточно для - 77 - того,чтобы начать исследование машинного кода (см.Раздел 8.5 [Исследование памяти]). Этот адрес также сохраняется как значение рабочей переменной `$_' (см.Раздел 8.9 [Рабочие переменные]). `disassemble' Эта специальная команда служит для вывода диапазона памяти в виде машинных инструкций. По умолчанию выводиться функция, окружающая значения PC в выбранной секции. Одиночный параметр этой команды указывает на значение PC; GDB выводит функцию, окружающую это значение. Два параметра определяют диапазон адресов для вывода (первый включается, второй исключается). Мы можем использовать `disassemble', чтобы просмотреть диапазон объектного кода, показанный в примере применения команды `info line' (этот пример показывает машинные инструкции SPARC): (gdb) disas 0x63e4 0x6404 Dump of assembler code from 0x63e4 to 0x6404: 0x63e4 : ble 0x63f8 0x63e8 : sethi %hi(0x4c00), %o0 0x63ec : ld [%i1+4], %o0 0x63f0 : b 0x63fc 0x63f4 : ld [%o0+4], %o0 0x63f8 : or %o0, 0x1a4, %o0 0x63fc : call 0x9288 0x6400 : nop End of assembler dump. - 78 - 8. Исследование данных Для исследования данных в вашей программе обычно используется команда `print' (сокращенно `p') или ее синонимом `inspect'. Эти команды вычисляют и выводят значение выражения, записанного на языке вашей программы (см.Главу 9 [GDB и различные языки программирования]). `print EXP' `print /F EXP' EXP - это выражение (на исходном языке). По умолчанию значение EXP выводится в формате, соответствующем его типу; Вы можете выбрать другой формат с помощью `/F', где F - буква, определяющая формат; см.Раздел 8.4 [Форматы вывода]. `print' `print /F' Если Вы опускаете EXP, GDB отображает последнее из "архива значений"; см.Раздел 8.8 [Архив значений]. Т.о., Вы можете взглянуть на то же самое значение в другом формате. Команда `x' исследует данные на более низком уровне. Она исследует указанные адреса в памяти и выводит их содержимое в определенном формате. См.Раздел 8.5 [Исследование памяти]. Если Вас интересует информация о типах или о том, как объявлены поля структуры или класса, вместо команды `print' лучше воспользоваться командой `ptype EXP'. См.Главу 10 [Исследование таблицы символов]. 8.1. Выражения `print' и многие другие команды GDB принимают в качестве параметра выражение и вычисляют его значение. В выражениях GDB могут использоваться любые допустимые в исходном языке программирования константы, переменные и операторы, включая условные выражения, вызовы функций, операторы приведения типа и строковые константы. К сожалению, символы, определенные командой препроцессора `#define', не включаются. - 79 - В новой версии GDB поддерживает в выражениях константы-массивы. Синтаксис: ELEMENT, ELEMENT.... Например, вы можете использовать команду `print {1 2 3}', чтобы создать массив в памяти, зарезервированной для программных нужд. По причине широкого распространения C, большинство выражений в примерах этого руководства, написаны на C. Для получения информации об использовании выражений на других языках, см.Главу 9 [GDB и различные языки программирования]. В этом разделе мы обсудим операторы, которые Вы можете использовать в выражениях GDB независимо от используемого Вами языка программирования. Приведения типов поддерживается во всех языках, а не только в C, так как бывает полезно представить число как указатель, чтобы исследовать структуру по этому адресу в памяти. В дополнение к общим для всех языков программирования операторам, GDB поддерживает следующие операторы: `@' `@' - бинарный оператор обработки областей памяти как массивов. См.Раздел 8.3 [Исскуственные массивы]. `::' `::' позволяет Вам работать с переменными того файла или функции, в которых они определены. См.Раздел 8.2 [Программные переменные]. `{TYPE} ADDR' Ссылается на объект типа TYPE, хранящийся в памяти по адресу ADDR. ADDR может быть любым выражением, значение которого - целое число или указатель (но вокруг бинарных операторов, также, как и вокруг оператора приведения типа, требуются круглые скобки). Эта конструкция позволяет обратиться к ADDR, независимо от предполагаемх типов данных. - 80 - 8.2. Программные переменные Чаще всего в качестве выражения используется имя переменной вашей программы. Переменные в выражениях сопоставляются выбранной процедурной секции см.Раздел 6.3 [Выбор процедурной секции]); они должны быть либо глобальными (или статическими), либо видимыми из точки выполнения в данной процедурной секции, согласно с правилами видимости языка программирования. Это означает, что в функции foo (a) int a; { bar (a); { int b = test (); bar (b); } } Вы можете исследовать или пользоваться переменной `a' всякий раз, когда ваша программа выполняется в пределах функции `foo', а пользоваться или исследовать переменную `b' Вы можете только в то время, когда ваша программа выполняется внутри блока, в котором `b' объявлена. Есть одно исключение: Вы можете ссылаться на переменную или функцию, имеющую смысл в одиночном исходном файле, даже если место текущего выполнения находится не в нем. Но может существовать более чем одна переменная или функция с одним и тем же именем (в различных исходных файлах). Если это так, обращение по этому имени приводит к непредсказуемым результатам. По желанию, Вы можете указать на статическую переменную в конкретной функции или файле, используя двойное двоеточие (`::'): - 81 - FILE::VARIABLE FUNCTION::VARIABLE Здесь FILE или FUNCTION - имя блока для статической переменной VARIABLE. В первом случае Вы можете использовать кавычки, чтобы GDB рассматривал имя файла как одно слово; например, чтобы вывести глобальное значение переменной `x', определенной `f2.c': (gdb) p 'f2.c'::x Такое использование `::' редко конфликтует с подобным использованием той же записи на C++. GDB также поддерживает в выражениях оператор C++ определения области видимости GDB. Предупреждение: Иногда, в определенной точке функции (сразу при входе или выходе из нового блока) может показаться, что у локальной переменной ошибочное значение. Вы можете столкнуться с этой проблемой при пошаговом выполнении по одной машинной инструкции. Она возникает из-за того, что на многих машинах при установке процедурной секции используется более одной инструкции (включая определения локальных переменных); если Вы производите выполнение по одной машинной инструкци, может показаться, что переменная имеет ошибочное значение, пока процедурная секция не будет полностью построена. При выходе, для ликвидации процедурной секции, также обычно требуется более одной машинной инструкции. Определение локальных переменных может происходить после начала пошагового выполнения этих инструкций. 8.3. Искусственные массивы Иногда требуется вывести несколько объектов одного типа, последовательно расположенных в памяти; часть массива или динамический массив, определяемый в программе только указателем. - 82 - Это можно сделать, обращаясь к непрерывному отрезку памяти, как к искусственному массиву, используя бинарную операцию `@'.В качестве левого операнда `@' должен выступать первый элемент требуемого массива, как индивидуальный объект. Правым операндом должна быть требуемая длина массива. Результат операции - массив, элементы которого имеют тот же тип, что и левый аргумент. Первым элементом массива является левый аргумент; второй элемент формируется из байтов памяти, непосредственно следующих за содержащими первый элемент, и т.д. Например, если в программе говорится int *array = (int *) malloc (len * sizeof (int)); то Вы можете вывести содержимое `array' с помощью p *array@len Левый операнд операции `@' должен постоянно существовать в памяти. Значения-массивы, полученные операцией `@', ведут себя, подобно остальным массивам, и приводятся к указателям при использовании их в выражениях. Искусственные массивы чаще всего появляются в выражениях посредством архива значений (см.Раздел 8.8 [Архив значений]). Приведение типа - другой способ создания искусственного массива. Оно интерпретирует значение как массив. Значение не обязано находиться в памяти. (gdb) p/x (short[2])0x12345678 $1 = {0x1234, 0x5678} Если Вы задаете массив, как `(TYPE[])VALUE', GDB для удобства вычисляет количество элементов в нем (как `sizeof(VALUE)/sizeof(TYPE)'): (gdb) p/x (short[])0x12345678 $2 = {0x1234, 0x5678} Иногда не достаточно использовать механизм искусственного массива; в сложных структурах данных, интересующие нас элементы могут не быть - 83 - смежными - например, если Вас интересуют значения указателей в массиве. В этой ситуации полезно использовать рабочую переменную (см.Раздел 8.9 [Рабочие переменные]), как счетчик в команде, выводящей первое интересуещее нас значение, а затем повторять ее нажатием RET. Например, пусть у Вас есть массив указателей на структуры `dtab', и Вас интересует значение поля `fv' в каждой структуре. Ниже приведен пример ваших возможных действий: set $i = 0 p dtab[$i++]->fv RET RET ... 8.4. Форматы вывода По умолчанию GDB выводит значение, согласуясь с его типом, что не всегда отвечает Вашему желанию. Например, Вы можете пожелать вывести число в шестнадцатеричной записи или указатель - в десятичной. Или Вы можете пожелать просмотреть данные по некоторому адресу в памяти в виде символьной строки или инструкции. Для этого при выводе значения определите "формат вывода". Проще всего использовать форматы вывода для вывода уже сосчитаного выражения. Такой вывод осуществляется заданием параметра команды `print' в виде косой черты (`/') и символа формата. Поддерживаются следующие символы формата: `x' Рассмотреть биты значения, как целое, и вывести целое в шестнадцатеричной записи. `d' Вывести число, как десятичное целое со знаком. `u' Вывести число, как беззнаковое десятичное целое. - 84 - `o' Вывести число, как восьмеричное целое. `t' Вывести число, как двоичное целое. Буква `t' означает "two". Замечание: `b' не используется, так как эти символы формата также используются в команде `x', где `b' означает "byte"; см.Раздел 8.5 [Исследование памяти]. `a' Вывести адрес, одновременно, как абсолютный (в шестнадцатеричной записи) и как отступ от ближайшего предыдущего символа. Вы можете использовать этот формат для того, чтобы определить, где (в какой функции) расположен этот адрес. (gdb) p/a 0x54320 $3 = 0x54320 <_initialize_vx+396> `c' Рассмотреть как целое и вывести как литерную константу. `f' Рассмотреть биты значения как число с плавающей точкой и вывести, используя обычный синтаксис для чисел с плавающей точкой. Например, чтобы вывести счетчик команд в шестнадцатеричной записи (см.Раздел 8.10 [Регистры]), наберите p/x $pc Обратите внимание, что перед косой чертой (`/') не требуется пробела, т.к., имена команд GDB ее не содержат. Чтобы вывести последнее значение из "архива значений" в другом формате, Вы можете воспользоваться командой `print' с одним параметром - символом формата (без выражения). Например, `p/x' выведет последнее - 85 - значение в шестнадцатеричной записи. 8.5. Исследование памяти Вы можете использовать команду `x' для просмотра памяти в любом из следующих, независимо от типов данных вашей программы. `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' Полуслово (два байта). - 86 - `w' Слово (четыре байта). Изначально используется по умолчанию. `g' 8-байтовое слово. Каждый раз, когда Вы определяете размер элемента для формата `x', этот размер используется по умолчанию при последующем использовании формата `x'. (Для форматов `s' и `i' размер элемента игнорируется и обычно не пишется). ADDR, начальный адрес отображения ADDR - адрес, с которого GDB должен начать отображение памяти. Значение выражения не обязано быть указателем (хотя может быть им); оно всегда интерпретируется, как адрес байта в памяти. См.Раздел 8.1 [Выражения] для получения большей информации о выражениях. По умолчанию ADDR - это адрес, следующий за последним изученным адресом, но значение ADDR, используемое по умолчанию, устанавливается и некоторыми другими командами: `info breakpoints' (адрес последней упомянутой точки останова), `info line' (начальный адрес строки) и `print' (если Вы используете эту команду для отображения значения из памяти). Например, `x/3uh 0x54320' запрашивает для вывода в формате беззнакового десятичного целого (`u') три полуслова (`h') из памяти, начиная с адреса `0x54320'. `x/4xw $sp' выводит четыре слова (`w') с вершины стека (здесь `$sp' подразумевает указатель вершины стека; см.Раздел 8.10 [Регистры]) в шестнадцатеричной записи (`x'). Так как буквы, обозначающие размер элемента, отличаются от букв, определяющих формат вывода, то их порядок не имеет значения. Спецификации вывода `4xw' и `4wx' подразумевают одно и то же. (Однако, число N должно быть первым; `wx4' не сработает). Хотя размер элемента U игнорируется для форматов `s' и `i', Вы, тем не менее, можете воспользоваться числом повторений N; например, `3i' - 87 - показывает, что Вы желаете вывести три машинные инструкции, включающие какие-либо операнды. Вы можете читать машинные инструкции также с помощью команды `disassemble';см.Раздел 7.4 [Источник и машинный код]. Все параметры команды `x', используемые по умолчанию, предназначены для того, чтобы облегчить продолжение сканирования памяти с минимальными спецификациями последующих использований `x'. Например, после того, как Вы просмотрели три машинные инструкции с помощью `x/3i ADDR', Вы можете просмотреть следующие семь, используя просто `x/7'. Если Вы повторяете команду `x' нажатием RET, число повторений N остается прежним; другие параметры берутся по умолчанию, как для последовательных использований `x'. Адреса и их содержимое, выводимые командой `x', не сохраняются в архиве значений, т.к. их часто бывает слишком много. Вместо этого, GDB допускает их последующее использование в выражениях, как значения рабочих переменных `$_' и `$__'. После команды `x', последний исследуемый адрес можно использовать в выражениях в виде рабочей переменной `$_'. Содержимое этого адреса, как изученное, можно использовать в виде рабочей переменной `$__'. Если команде `x' задано число повторений, адрес и его содержимое сохраняются из последнего выведенного элемента памяти, который, если на последней строке выводилось несколько элементов, отличается от последнего выведенного адреса. 8.6. Автоматическое отображение Если Вам необходимо часто выводить значение какого-то выражения (чтобы увидеть, как оно меняется), Вы можете добавить это выражение в список автоматического отображения, чтобы GDB выводил его значение всякий раз при остановке вашей программы. Каждому выражению, добавленному в список, присваивается идентефикационный номер; Вы указываете его при удалении выражения из списка. Автоматическое отображение выглядит подобным образом: - 88 - 2: foo = 38 3: bar[5] = (struct hack *) 0x3804 Это отображение показывает номера элементов, выражения и их текущие значения. Как и при отображении с помощью `x' или `print', Вы можете определить предпочитаемый формат вывода; фактически, команда `display' использует `print' или `x', в зависимости от того, как Вы указываете формат: она пользуется `x', если Вы указываете размер элемента или один из двух форматов (`i' или `s'), которые поддерживаются только `x'; в других случаях она использует `print'. `display EXP' Добавить выражение EXP к списку автоматического отображения. См.Раздел 8.1 [Выражения]. Команда `display' не повторяется при нажатии RET. `display/FMT EXP' Если FMT определяет только формат вывода, но не размер элемента и не число повторений, выражение EXP добавляется в список автоматического отображения, но его отображение осуществлятся в указанном формате FMT. См.Раздел 8.4 [Форматы вывода]. `display/FMT ADDR' Если FMT является `i' или `s', или включает в себя размер элементов или их число, выражение ADDR добавляется, как адрес памяти, для исследования при каждой остановке программы. Под исследованием в данном случае подразумевается выполнение `x/FMT ADDR'. См.Раздел 8.5 [Исследование памяти]. Например, `display/i $pc' может быть полезна, чтобы при каждой остановке видеть следующую машинную инструкцию, которая будет выполняться (`$pc' - общее обозначение PC; см.Раздел 8.10 [Регистры]). - 89 - `undisplay DNUMS...' `delete display DNUMS...' Удалить элементы под номерами DNUMS из списка автоматического отображения. `undisplay' не повторяется при нажатии RET. (Иначе, Вы сразу получили бы сообщение об ошибке `No display number ...'). `disable display DNUMS...' Отключить отображение элементов под номерами DNUMS. Отключенные элементы не выводятся автоматически, но и не забываются. Впоследствии их можно подключить. `enable display DNUMS...' Подключить к отображению элементы под номерами DNUMS. Для выражений этих элементов опять осуществляется автоматическое отображение до тех пор, пока Вы не отключите его. `display' Отобразить текущие значения выражений из списка, точно так же, как при останове вашей программы. `info display' Вывести список выражений, ранее установленных для автоматического отображения; каждое - с номером элемента, но без значения. Список включает отключенные выражения с пометкой об отключении. Он также включает в себя выражения, которые не выводятся прямо сейчас, т.к. обращаются к локальным динамическим переменным, не доступным в текущее время. Если отображаемое выражение обращается к локальным переменным, оно имеет смысл только в том лексическом контексте, для которого оно рассматривалось. Такие выражения отключаются, как только их переменные перестают быть определенными в исполняемой области. Например, если внутри функции с аргументом `last_char' Вы дадите команду `display last_char', GDB будет отображать этот аргумент до тех пор, пока программа будет останавливаться внутри этой функции. Как только она остановится там, где нет переменной `last_char', отображение будет - 90 - автоматически отключено. Вы сможете снова подключить его при следующей остановке программы там, где `last_char' будет иметь смысл. 8.7. Установки вывода 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', Вы получите один и тот же текст для цепочек вызовов на всех машинах, независимо от того, включают ли они - 91 - указатели параметров. `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 показывает соответствующие номер строки и имя исходного файла. По вашему желанию GDB может выводить символьную форму только в том случае, если выводимый адрес достаточно близок к ближайшему предшествующему символу: `set print max-symbolic-offset MAX-OFFSET' После этой команды GDB выводит символьные формы только тех адресов, для которых смещение самого адреса от ближайшего - 92 - предшествующего символа меньше, чем MAX-OFFSET. По умолчанию значение MAX-OFFSET равно нулю, в этом случае GDB выводит адрес в символьной форме, если хоть какой-нибудь символ предшествует ему. `show print max-symbolic-offset' Запросить информацию о максимальном смещении, для которого GDB выводит символьную форму адреса. Если Вы не знаете, на что указывает какой-либо указатель, попробуйте `set print symbol-filename on'. Затем Вы сможете установить имя исходного файла и месторасположение в нем переменной, на которую указывает указатель, используя `p/a POINTER'. (Эта команда выводит адрес в символьной форме). В примере, GDB показывает, что переменная `ptt', указывает на другую переменную `t', определенную в файле `hi2.c': (gdb) set print symbol-filename on (gdb) p/a ptt $4 = 0xe008 Предупреждение: Для указателей, указывающих на локальную переменную, `p/a' не показывает символьное имя и имя файла, которому принадлежит ссылка, даже если установлена соответствующая опция `set print' (`on'). Следующие установки управляют выводом объектов: `set print array' `set print array on' Структурный вывод массивов. Этот формат наиболее удобен для чтения, но занимает больше места. По умолчанию отключен. `set print array off' Вернуться к сжатому формату вывода массивов. `show print array' Показать, в каком формате выводятся массивы. - 93 - `set print elements NUMBER-OF-ELEMENTS' Установить ограничение на количество выводимых элементов массива. Вывод большого массива будет прерван после того, как будет выведено установленное командой `set print elements' число элементов. Это ограничение также касается отображения строк. Установка NUMBER-OF-ELEMENTS на ноль означает, что вывод ничем не ограничен. `show print elements' Показать, сколько элементов больших массивов будет выведено GDB. Если число равно нулю, вывод не ограничен. `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"} Этот формат устанавливается по умолчанию. - 94 - `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' Выводить объединения, содержащиеся в структурах. Устанавливается по умолчанию. `set print union off' Не выводить объединения, содержащиеся в структурах. `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; - 95 - 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 = {...}} Следующие установки представляют интерес при отладке программ на C++: `set print demangle' `set print demangle on' Выводить идентификаторы C++ в их изначальной, а не закодированной ("mangled") форме, передаваемой ассемблеру и компоновщику для сборки с контролем типа. По умолчанию `on'. `show print demangle' Показать, в какой форме выводяться идентификаторы C++. `set print asm-demangle' `set print asm-demangle on' Выводить идентификаторы C++ в их исходной форме, а не в закодированной, при этом код ассемблера выводится в виде дизассемблированных инструкций. По умолчанию отключено. `show print asm-demangle' Показать, в какой форме выводятся идентификаторы C++ при выводе кода ассемблера. - 96 - `set demangle-style STYLE' Выбрать одну из нескольких схем кодирования, используемых различными компиляторами для представления идентификаторов C++. Параметр STYLE может быть следующим: `auto' Позволить GDB выбрать стиль декодирования посредством изучения вашей программы. `gnu' Декодировать, основываясь на алгоритме кодирования GNU компилятора C++ (`g++'). Устанавливается по умолчанию. `lucid' Декодировать, основываясь на алгоритме кодирования Lucid компилятора C++ (`lcc'). `arm' Декодировать, используя алгоритм из `C++ Annotated Reference Manual'. Предупреждение: одна эта установка не достаточна для отладки исполнимых программ, сгенерированных `cfront'. Для нее GDB требует дальнейших усовершенствований. `foo' Показать перечень форматов. `show demangle-style' Отобразить текущий стиль кодирования, используемый для декодирования идентификаторов C++. `set print object' `set print object on' При отображении указателя на объект, предпочтительнее идентифицировать (используя таблицу виртуальных функций) фактический (полученный) тип объекта, а не объявленный. - 97 - `set print object off' Отображать только объявленный тип объекта, независимо от таблицы виртуальных функций. Устанавливается по умолчанию. `show print object' Показать, какой тип (фактический или объявленный) объекта выводится. `set print vtbl' `set print vtbl on' Структурный вывод таблиц виртуальных функций C++. По умолчанию отключена. `set print vtbl off' Не осуществлять структурный вывод таблиц виртуальных функций C++. `show print vtbl' Показать, производиться ли структурный вывод таблиц виртуальных функций C++. 8.8. Архив значений Значения, выведенные командой `print', сохраняются в архиве значений GDB, что позволяет Вам обращаться к ним в других выражениях. Значения сохраняются, пока таблица символов не будет считана заново или сброшена (например, при использовании команды `file' или `symbol-file'). При изменении таблицы символов архив значений сбрасывается, т.к. значениями могут быть указатели на типы, определенные в таблице символов. Выведенным значениям задаются архивные номера, с помощью которых Вы можете обращаться к ним. Номера присваиваются последовательно, начиная с единицы. Команда `print' показывает архивный номер, назначаемый значению, выводя перед ним `$NUM = ', где NUM - это архивный номер. Для обращения к какому-либо предшествующему значению используйте символ `$', сопровождаемый архивным номером. Маркеры вывода команды - 98 - `print' предназначены для напоминания Вам о номерах. Просто `$' ссылается на последнее значение в архиве, а `$$' - на предпоследнее. `$$N' ссылается на N-ое от конца значение. `$$1' эквивалентно `$$', а `$$0' эквивалентно `$'. Пусть, например, Вы только что вывели указатель на структуру и хотите видеть ее содержимое. Для этого достаточно набрать p *$ Если у Вас есть цепочка структур и компонента `next' указывает на следующую, Вы можете вывести содержимое следующей структуры, набрав: p *$.next Вы можете выводить последовательные звенья в цепочке повтором этой команды, который осуществляется простым нажатием RET. Обратите внимание, что в архив записываются значения, а не выражения. Если значение `x' равно 4, и Вы наберете: print x set x=5 то значение, записанное в архив значений командой `print', будет по-прежнему равно 4, хотя значение `x' изменилось. `show values' Вывести из архива последние десять значений, с их номерами. Эта команда подобна команде `p $$9', повторенной десять раз, за исключением того, что `show values' не изменяет архив значений. `show values N' Вывести десять архивных значений, расположенных вокруг элемента под номером N. - 99 - `show values +' Вывести десять архивных значений, следующих сразу после последнего выведенного значения. Если доступных значений больше нет, `show values +' ничего не выводит. Нажатие RET для повтора `show values N' действует также, как `show values +'. 8.9. Рабочие переменные GDB поддерживает рабочие переменные, которыми Вы можете пользоваться в пределах GDB, чтобы сохранять значение и обращаться к нему позже. Эти переменные существуют только в пределах GDB; они не входят в вашу программу и их установка не влияет на дальшейшее выполнение вашей программы - Вы можете свободно пользоваться ими. Имена рабочих переменных начинаются с `$'. Любое имя с приставкой `$' может использоваться для рабочей переменной, если только оно не является предопределенным именем специфического машинного регистра (см.Раздел 8.10 [Регистры]). (В отличие от имен рабочих переменных, ссылки в архиве значений - это числа, сопровождаемые `$'. См.Раздел 8.8 [Архив значений]). Вы можете сохранять значения в рабочих переменных с помощью выражения присваивания, как если бы Вы устанавливали переменную в вашей программе. Например: set $foo = *object_ptr сохраняет в `$foo' значение объекта, на который указывает `object_ptr'. Первое использование рабочей переменной создает ее, но ее значение `void', пока Вы не присвоите ей новое. Вы можете в любое время изменить значение с помощью присваивания. - 100 - Рабочие переменные не имеют определенного типа. Вы можете присваивать рабочей переменной любой тип значения, включая структуры и массивы, даже если у этой переменной уже было значение другого типа. При использовании в выражении, рабочая переменная имеет тип своего текущего значения. `show convenience' Вывести перечень используемых рабочих переменных с их значениями. Сокращается до `show con'. Рабочие переменные можно использовать в качестве увеличивающегося счетчика или продвигающегося указателя. Например, чтобы вывести какое-нибудь поле последовательных элементов массива структур: set $i = 0 print bar[$i++]->contents Повторяйте эту команду нажатием RET. Некоторые рабочие переменные GDB создает автоматически и присваивает им полезные (по его мнению) значения. `$_' Переменная `$_' автоматически устанавливается командой `x' как последний исследованный адрес (см.Раздел 8.5 [Исследование памяти]). Другие команды, которые устанавливают адрес для исследования, используемый по умолчанию командой `x', также присваивают ей упомянутый адрес; так действуют, например, `info line' и `info breakpoint'. Переменная `$_' имеет тип `void*', если только она не установлена командой `x'; в этом случае ее тип - указатель на тип переменной `$__'. `$__' Переменная `$__' автоматически устанавливается командой `x' как содержимое последнего исследованного адреса. Ее тип соответствует формату, в котором это значение выводится. - 101 - `$_exitcode' Переменной `$_exitcode' автоматически присваивается код выхода при завершении отлаживаемой программы. 8.10. Регистры В выражениях Вы можете обращаться к содержимому машинных регистров, обозначая их, как переменные с именем, начинающимся `$'. Имена регистров зависят от машины; для вывода имен регистров вашей машине, используйте `info registers'. `info registers' Вывести имена и содержимое всех регистров, исключая арифметические регистры (в выбранной процедурной секции). `info all-registers' Вывести имена и содержимое всех регистров, включая арифметические регистры. `info registers REGNAME ...' Вывести соотнесенное значение каждого регистра, определенного REGNAME. Ниже детально обсуждается, как значения регистров соотносятся с выбранной процедурной секцией. REGNAME - любое допустимое на вашей машине имя регистра, `$' в начале имени можно опустить. GDB распознает четыре стандартных имени регистров, которые допустимы (в выражениях) на большинстве машин - если только они не противоречат канонической мнемонике архитектуры. Имена регистров `$pc' и `$sp' используются для PC и указателя вершины стека соответственно. `$fp' используется, как имя регистра, содержащего указатель на текущую процедурную секцию, а `$ps' - как имя регистра состояние процессора. Например, Вы можете вывести PC в шестнадцатеричной записи с помощью p/x $pc или вывести следующую исполняемую инструкцию с помощью - 102 - x/i $pc или увеличить указатель вершины стека на четыре set $sp += 4 Замечание: таким образом можно удалить слово из стека на машинах, в которых стек в памяти растет вниз. (Таких машин сейчас большинство). При этом предполагается, что выбрана внутренняя процедурная секция; использование `$sp' недопустимо, если выбрана другая секция. Для извлечения секции из стека целиком, воспользуйтесь `return'; см.Раздел 11.4 [Возврат из функции]. Эти четыре имени регистров можно использовать при работе на вашей машине, даже если Ваша машина имеет другую каноническую мнемонику, если, конечно, эти имена не противоречат ей. Команда `info registers' показывает канонические имена. В SPARC, например, `info registers' отображает регистр состояния процессора, как `$psr', но Вы можете обращаться к нему `$ps'. При исследовании обычного регистра, GDB всегда рассматривает его содержимое, как целое. Некоторые машины имеют специальные регистры, которые содержат только числа с плавающей точкой; их содержимое рассматривается, как числа с плавающей точкой. Обратится к содержимому обычного регистра, как к значению с плавающей точкой, нельзя (хотя Вы можете вывести его, как значение с плавающей точкой с помощью `print/f $REGNAME'). Некоторые регистры имеют жесткие "исходные" и "линеаризованные" форматы данных. Это означает, что формат данных, в котором операционная система сохраняет содержимое регистра, не совпадает с теми, которые обычно воспринимаются программой. Например, регистры сопроцессора с плавающей точкой 68881 всегда сохраняют значения в формате "extended" (линеаризованном), но все программы на C работают с - 103 - форматом "double" (виртуальном). В подобных случаях, GDB обычно работает только с виртуальным форматом (формат, имеющий смысл в вашей программе), но команда `info registers' выводит данные в обоих форматах. Обычно значения регистров соотносятся с выбранной процедурной секцией (см.Раздел 6.3 [Выбор процедурной секции]), т.е. Вы получаете значение, которое содержалось бы в регистре, если бы произошел выход из всех дальнейших процедурных секций и сохраненные регистры были бы восстановлены. Для того, чтобы увидеть истинное содержимое аппаратных регистров, Вы должны выбрать внутреннюю секций (с помощью `frame 0'). Однако, GDB, исходя из машинного кода, сгенерированного вашим компилятором, должен установить, где сохранены регистры. Если некоторые регистры не сохранены или GDB не в состоянии найти сохраненные регистры, выбор процедурной секции не имеет значения. `set rstack_high_address ADDRESS' На семействе процессоров AMD 29000, регистры сохраняются в "стеке регистров". У GDB нет средств определить размер этого стека, что может привести к тому, что GDB будет обращаться к несуществующей памяти. Если необходимо, Вы можете избежать этой проблемы с помощью команды `set rstack_high_address'. Ее параметром должен быть адрес, шестнадцатеричная запись которого начинается с `0x'. `show rstack_high_address' Отобразить текущее ограничение на размер стека регистров в семействе процессоров AMD 29000. 8.11. Аппаратные средства поддержки вычислений с плавающей точкой В некоторых конфигурациях GDB может выдавать Вам больше информации о состоянии аппаратных средств поддержки вычислений с плавающей точкой. - 104 - `info float' Отобразить аппаратную информацию об устройствах поддержки вычислений с плавающей точкой. Ее точное содержание и размещение зависит от микросхемы поддержки вычислений с плавающей точкой. В настоящее время, `info float' поддерживается на ARM и x86 машинах. 9. GDB и различные языки программирования Хотя языки программирования в общем похожи, их синтаксис не всегда совпадает. Например, в ANSI C, разыменование указателя `p' выполняется операцией `* p', а в Modula-2 она выглюдит как `p^'. Представление (и отображение) значений также могут быть различными. Шестнадцатеричные числа в C представляются подобно `0x1ae', в то время как в Modula-2 они представляются подобно `1AEH'. В GDB встроена специальная информация о некоторых языках, которая позволяет записывать выражения, подобные вышеупомянутым, на языке вашей программы, и позволяет GDB выводить значения в допустмом языком вашей программы виде. Язык, которым Вы пользуетесь при построении выражений, называется "рабочим языком". 9.1. Переход с однго языка на другой Существует два способа выбора рабочего языка: либо GDB устанавливает его автоматически, либо Вы можете это сделать самостоятельно. Для этой цели Вы можете воспользоваться командой `set language'. По умолчанию GDB устанавливает язык автоматически. Рабочий язык используется, чтобы определить, как интерпретировать вводимые вами выражения, как выводить значения и т.п. В дополнение к основному рабочему языку, каждый исходный файл, с которым работает GDB, имеет свой собственный рабочий язык. Для некоторых форматов объектных файлов компилятор может указывать, на каком языке написан конкретный исходный файл. Однако, чаще всего GDB распознает язык по имени файла. От языка исходного файла зависит, - 105 - будут ли идентификаторы C++ декодированы; т.о. `backtrace' может показать каждую секцию соответственно его исходному языку. Нельзя установить язык исходного файла из GDB. Более общая проблема возникает, когда Вы используете программу, такую, как `cfront' или `f2c', которая имитирует C, но написана на другом языке. В этом случае нужно, чтобы при ее C-выводе использовалась директива `#line'; т.о. GDB корректно определит, на каком языке написан исходный текст первоначальной программы, и выведет этот текст, а не имитированный. 9.1.1. Соответствие расширений файлов и языков Если исходный файл имеет одно из представленных ниже расширений, GDB воспринимает это как указание на обозначенный таким образом язык. `.mod' Исходный файл Modula-2 `.c' Исходный файл C `.C' `.cc' `.cxx' `.cpp' `.cp' `.c++' Исходный файл C++ `.ch' `.c186' `.c286' Исходный файл языка CHILL. - 106 - `.s' `.S' Исходный файл Ассемблера. Восприниматся почти также, как C, но GDB не пропускает вводные части функций при пошаговом выполнении. 9.1.2. Установка рабочего языка Если GDB установил язык автоматически, выражения в сеансе отладки и в вашей программе интерпретируются одинаково. По желанию, Вы можете установить язык сами. Для этого воспользуйтесь командой `set language LANG', где LANG - название языка, например, `c' или `modula-2'. Чтобы получить перечень поддерживаемых языков, наберите `set language'. Установка языка вручную запрещает автоматическое переключение рабочего языка. Она может привести к неприятным последствиям, если Вы пытаетесь отладить программу, в то время, как рабочий язык не совпадает с исходным языком, т.е. выражения, допустимые в обоих языках, интерпретируются по-разному. Например, если текущий исходный файл написан на C, а рабочий язык - Modula-2, команда, подобная: print a = b + c может не привести к ожидаемому результату. В C эта запись означает сложение `b' и `c' и помещение результата в `a'. Выведенный результат будет значением `a'. В Modula-2, она означает сравнение `a' с результатом `b+c' и выдается значение типа `BOOLEAN'. 9.1.3. Распознавание GDB исходного языка Для автоматической установки языка, используйте `set language local' или `set language auto'. После такой команды при остановке вашей программы в процедурной секции (обычно, на точке останова), GDB будет устанавливать рабочий язык в этой секции. Если язык процедурной секции неизвестен (т.е. функция или блок, соответствующие секции, - 107 - определялись в исходном файле, не имеющем распознаваемого расширения), текущий рабочий язык не меняется, а GDB выдает предупреждающее сообщение. Для большинства программ, написанных целиком на одном языке, автоматическая установка языка может показаться необязательной. Однако, в основной программе, написанной на одном исходном языке, могут использоваться программные модули и библиотеки, написанные на другом языке. Использование в этом случае `set language auto' позволит Вам не беспокоиться об установке рабочего языка. 9.2. Отображение языка Ниже описаны команды, которые помогут Вам определить, какой язык является рабочим, а также, на каком языке написан исходный файл. `show language' Отобразить текущий рабочий язык (именно его Вы можете использовать в командах типа `print' для построения и вычисления выражений, в которые могут включаться переменные вашей программы). `info frame' Отобразить исходный язык данной процедурной секции. Этот язык становится рабочим, если используется идентификатор из этой процедурной секции. См.Раздел 6.4 [Информация о процедурной секции], для получения большей информации об этой команде. `info source' Отобразить исходный язык данного исходного файла. См.Главу 10 [Исследование таблицы символов], для получения большей информации об этой команде. - 108 - 9.3. Проверка принадлежности типу и диапазону Предупреждение: В этой версии GDB присутствуют команды для проверок принадлежности типу и диапазону, но семантически они не реализованы. Этот раздел описывает их предполагаемые действия. Некоторые языки обеспечивают защиту от более или менее общих ошибок с помощью статических и динамических проверок. Она включает проверку типов аргументов функций и операндов операторов и предотвращает математическое переполнение во время выполнения. Проверки такого рода помогают убедиться в том, что программа откомпилирована без ошибок смешения типов, а во время выполнения программы не возникают ошибки выхода за пределы диапазона. По вашему желанию, GDB может проводить подобные проверки. Хотя GDB не проверяет утверждения вашей программы, он может проверять непосредственно вводимые выражения, например, командой `print'. Как и в случае рабочего языка, GDB может автоматически решать, выполнять ли проверку, основываясь на исходном языке вашей программы. См.Раздел 9.4 [Поддерживаемые языки], для получения информации об установках по умолчанию в поддерживаемых языках. 9.3.1. Краткий обзор проверки соответствия типов Некоторые языки, такие, как Modula-2, имеют жесткое определение типа, т.е. аргументы операций и функций должны иметь правильный тип, в противном случае мы столкнемся с ошибкой. Описанные здесь проверки предотвращают ошибки смешения типов, которые могут послужить причиной каких-нибудь неприятностей при выполнении. Например, 1 + 2 => 3 но error--> 1 + 2.3 Во втором примере ошибка, потому что `CARDINAL' 1 не совместим по - 109 - типу с `REAL' 2.3. GDB может работать в трех режимах: пропускать проверку соответствия типов; определять любые несоответствия, как ошибки, и прекращать обработку выражения; или выводить предупреждающие сообщения при смешении типов и продолжать вычисление выражения. В последнем случае, GDB обработает выражение из второго примера, но выведет предупреждающее сообщение. Даже если Вы запретили проверку типов, GDB может прекратить обработку выражения по другим причинам. Например, GDB не может складывать `int' и `struct foo'. Эти конкретные типы ошибок не имеют ничего общего с используемым языком и обычно возникают из выражений, подобных описанному выше, для которых нельзя указать никакого приемлимого способа вычисления. Степень строгости определения типов зависит от языка. Например, и Modula-2, и C требуют, чтобы операнды арифметических операций были числами. C допускает представление значений перечислимых типов и указателей в виде чисел, т.е. они допустимы в качестве аргументов арифметических операций. Для получения большей информации по отдельным языкам, см.Раздел 9.4 [Поддерживаемые языки]. GDB обеспечивает некоторые дополнительные команды для проверки типов: `set check type auto' Подключить или отключить контроль типов, в зависимости от текущего рабочего языка. См.Раздел 9.4 [Поддерживаемые языки], для получения информации об установках по умолчанию для поддерживаемых языков. `set check type on' `set check type off' Подключить или отключить контроль типов, пренебрегая установкой по умолчанию для текущего рабочего языка. Выводит предупреждающее сообщение, если установка для рабочего языка не соответствует используемой по умолчанию. Если происходит смешение типов при - 110 - вычислении выражения, а контроль типов подключен, GDB выводит сообщение и прерывает вычисление выражения. `set check type warn' При смешении типов вывести предупреждающее сообщение, и попытаться вычислить выражение. Выражение, тем не менее, может быть невычислимо по другим причинам. Например, GDB не может складывать числа со структурами. `show type' Показать текущую установку проверки типов и способ ее установки (автоматически или нет). 9.3.2. Краткий обзор проверки диапазона В некоторых языках (типа Modula-2), выход за границы диапазона считается ошибкой; эти ошибки отслеживаются с помощью динамического контроля. Проверки диапазона служат для того, чтобы избежать переполнения при вычислениях и не допустить превышения индексами элементов массива границ индексации. GDB может работать в трех режимах: пропускать проверку диапазона; определять любые несоответствия, как ошибки, и прекращать обработку выражения; или выводить предупреждающие сообщения и продолжать вычисление выражения. Ошибки диапазона могут возникать при числовом переполнении, при превышении границы индексации или при использовании константы, не принадлежащей ни к одному типу. Однако, некоторые языки не рассматривают переполнение как ошибку. Во многих версиях C арифметическое переполнение вызывает "циклический переход" к меньшему значению. Например, если M - наибольшее целое, а S - наименьшее, то M + 1 => S Способы обработки переполнения являются особыми для конкретных языков, а в некоторых случаях - для отдельного компилятора или машины. - 111 - Для дальнейших сведений по отдельным языкам, см.Раздел 9.4 [Поддерживаемые языки]. GDB обеспечивает некоторые дополнительные команды для проверки диапазона: `set check range auto' Подключить или отключить контроль диапазона, в зависимости от текущего рабочего языка. См.Раздел 9.4 [Поддерживаемые языки], для получения информации об установках по умолчанию в поддерживаемых языках. `set check range on' `set check range off' Подключить или отключить контроль типов, пренебрегая установкой по умолчанию для текущего рабочего языка. Выводит предупреждающее сообщение, если установка не соответствует используемой по умолчанию. Если происходит ошибка диапазона, а контроль диапазона подключен, GDB выводит сообщение и прерывает вычисление выражения. `set check range warn' При выявлении ошибки диапазона GDB выведет предупреждающее сообщение, но попытается вычислить выражение. Тем не менее, вычисление выражения может быть неосуществимо по другим причинам, таким, как обращение к памяти, которой процесс не имеет (типичный пример для многих систем Unix). `show range' Показать текущую установку проверки диапазона и способ ее установки (автоматически или нет). - 112 - 9.4. Поддерживаемые языки GDB 4 поддерживает C, C++ и Modula-2. Некоторые особенности GDB могут использоваться в выражениях независимо от языка, который Вы используете: операторы GDB `@' и `::' и конструкция `{type}addr' (см.Раздел 8.1 [Выражения]) могут использоваться с конструкциями любого поддерживаемого языка. Следующие разделы подробно описывают, до какой степени каждый из исходных языков поддерживается GDB. Их нельзя рассматривать, как руководство по языкам; они лишь дают информацию о допустимых в GDB выражениях и о форматах ввода-вывода в различных языках. Существуют отдельные руководства по каждому из этих языков. 9.4.1. C и C++ Поскольку C и C++ близки друг к другу, многие средства поддержки GDB применимы к ним обоим. Такие ситуации описываются для обоих языков одновременно. Средства отладки C++ обеспечиваются совместно GNU-компилятором C++ и GDB. Следовательно, для эффективной отладки программы на C++, Вам следует пользоваться GNU-компилятором C++, `g++'. Для получения лучших результатов при отладке программ C++, используйте формат отладочной информации stabs. Вы можете указать его явно с помощью опции `-gstabs' или `-gstabs+' командной строки `g++'. См.Раздел "Опции отладки вашей программы или GNU CC" в "Using GNU CC". 9.4.1.1. Операторы C и C++ Операторы должны быть определены на значениях определенных типов. Например, оператор "+" определен на числах, но не на структурах. Операторы часто определяются на группах типов. - 113 - Для целей C и C++ поддерживаются следующие определения: * *Integral types* включают `int' с любым из спецификаторов класса памяти; `char' и `enum'. * *Floating-point types* включают `float' и `double'. * *Pointer types* включают все типы, определенные как `(TYPE *)'. * *Scalar types* включают все вышеперечисленное. Поддерживаются следующие операторы, перечисленные здесь в порядке возрастания приоритета: `,' Запятая или оператор последовательного выполнения. Выражения, разделенные запятыми в списке, выполняются слева направо; результатом всего выражения является результат последнего в списке. `=' Присваивание. Значение выражения приваивания - присвоенное значение. Определен на скалярных типах. `OP=' Используется в выражениях в форме `A OP= B' и интерпретируется, как `A = A OP B'. Имеет тот же приоритет, что и `='. OP может быть любым из операторов `|', `^', `&', `<<', `>>', `+', `-', `*', `/', `%'. `?:' Тернарный оператор. `A ? B : C' истолковывается как: если A, то B, иначе C (if A then B else C). A - обязательно целочисленного типа. `||' Логическое ИЛИ. Определен на целочисленных типах. - 114 - `&&' Логическое И. Определен на целочисленных типах. `|' Поразрядное ИЛИ. Определен на целочисленных типах. `^' Поразрядное ИСКЮЧАЮЩЕЕ ИЛИ. Определен на целочисленных типах. `&' Поразрядное И. Определен на целочисленных типах. `==, !=' Равенство и неравенство. Определены на скалярных типах. Значение этих выражений 0 для FALSE и отлично от нуля для TRUE. `<, >, <=, >=' Меньше, больше, не больше, не меньше. Определены на скалярных типах. Значение этих выражений 0 для FALSE и отлично от нуля для TRUE. `<<, >>' Сдвиг влево и сдвиг вправо. Определены на целочисленных типах. `@' Оператор GDB создания "искусственного массива" (см.Раздел 8.1 [Выражения]). `+, -' Сложение и вычитание. Определены на целочисленных типах, типах с плавающей точкой и типах указателей. `*, /, %' Умножение, деление и остаток. Умножение и деление определены на целочисленных типах и типах с плавающей точкой. Остаток определен на целочисленных типах. - 115 - `++, --' Инкремент и декремент. При использовании перед переменной, операция выполняется прежде, чем переменная используется в выражении. При использовании после переменной, сначала используется значение переменной. `*' Разыменование указателя. Определен на типах указателей. Имеет тот же приоритет, что и `++'. `&' Оператор получения адреса. Определен на переменных. Имеет тот же приоритет, что и `++'. Для C++ отладки, GDB использует `&' независимо от того, что позволяет C++: Вы можете использовать `&(&REF)' (или просто `&&REF'), чтобы исследовать адрес, по которому находится ссылающаяся переменная C++ (объявленная при помощи `&REF'). `-' Унарный минус. Определен на целочисленных типах и типах с плавающей точкой. Имеет тот же приоритет, что и `++'. `!' Логическое отрицание. Определен на целочисленных типах. Имеет тот же приоритет, что и `++'. `~' Оператор поразрядного дополнения. Определен на целочисленных типах. Имеет тот же приоритет, что и `++'. `., ->' Элемент структуры и pointer-to-structure member. Для удобства, GDB считает их эквивалентными, выбирая образ действия по контексту. Определены на данных типа `struct' или `union'. - 116 - `[]' Индексация массива. `A[I]' определяется как `*(A+I)'. Имеет тот же приоритет, что и `->'. `()' Список аргументов функции. Имеет тот же приоритет, что и `->'. `::' Оператор C++ определения области видимости. Определен на типах `struct', `union' и `class'. `::' Двойное двоеточие представляет оператор GDB определения блока описания (см.Раздел 8.1 [Выражения]). Имеет тот же приоритет, что и вышеописанный `::'. 9.4.1.2. Константы C и C++ GDB позволяет Вам выражать константы C и C++ следующими способами: * Целочисленные константы - последовательность цифр. Восьмеричные константы начинаются с `0' (нуля), а шестнадцатеричные константы - с `0x' или `0X'. Константы могут заканчиваться символом `l', что указывает на обработку их, как значений типа `long'. * Константы с плавающей точкой - последовательность цифр, сопровождаемая последующими десятичной точкой и другой последовательностью цифр. Возможно отсутствующий порядок может быть указан в форме `e[[+]|-]NNN', где NNN - еще одна последовательность цифр. `+' не обязателен для положительных показателей. * Перечислимые константы состоят из перечислимых идентификаторов, или их целочисленных эквивалентов. * Литерные константы - одиночные символы, заключенные в одиночные кавычки (`''), или числа - коды (обычно ASCII) соответствующих литер. В пределах кавычек, одиночная литера может быть представлена либо - 117 - буквой, либо "управляющей последовательностью", которая имеет форму `\NNN', где NNN - восьмеричное представление порядкового кода литеры; или форму `\X', где `X' является предопределенным специальным символом - например, `\n' для "newline". * Строковые константы - последовательности литерных констант, заключенные в двойные кавычки (` " '). * Константные указатели - целочисленные значения. Вы можете также записывать указатели на константы, используя оператор C `&'. * Константы-массивы - заключенные в фигурные скобки (`{' и `}') списки элементов, разделенных между собой запятой; например, `{1,2,3}' является массивом с тремя целочисленными элементами; `{{1,2}, {3,4}, {5,6}}' является three-by-two массивом (массивом из трех элементов, которые сами по себе являются массивами из двух элементов); а `{&"hi", &"there", &"fred"}' является массивом с тремя элементами-указателями. 9.4.1.3. Выражения C++ GDB имеет дополнительные возможности для интерпретации многих выражений C++. Предупреждение: GDB может отлаживать программы на C++, только если Вы компилировали их GNU-компилятором C++. Кроме того, C++ отладка зависит от использования дополнительной отладочной информации в таблице символов, и, таким образом, требует специальной поддержки. GDB обеспечивает эту поддержку только для формата отладочной информации stabs. В частности, если ваш компилятор генерирует a.out, MIPS ECOFF, RS/6000 XCOFF, или ELF с расширениями stabs таблицы символов, все подобные средства доступны. (В GNU CC, Вы можете использовать опцию `-gstabs', чтобы явно запросить расширения stabs отладки). С другой стороны, если формат объектного кода - стандартные COFF или DWARF в ELF, большая часть поддержки C++ в GDB не работает. - 118 - 1. Допускаются обращения к функции-атрибуту; Вы можете использовать выражения типа count = aml->GetOriginal(x, y) 2. Пока функция-атрибут активна (в выбранной процедурной секции), вашим выражениям доступно то же пространство имен, что и функции-атрибуту; т.е. GDB допускает неявные ссылки на указатель экземпляра класса `this' по тем же правилам, что и в C++. 3. Вы можете вызывать перегруженные функции; GDB разрешает правильно определенный вызов функции при одном условии - Вы должны использовать аргументы тех типов, которые запрашиваются вызываемой функцией. GDB не совершает преобразования, для выполнения которых требуются конструкторы или операторы, типы которых определяются пользователем. 4. GDB воспринимает переменные, объявленные как ссылки C++; Вы можете использовать их в выражениях, точно как Вы делаете на C++ - они автоматически разыменовываются. В списке параметров, показываемом при отображении процедурной секции, значения переменных-ссылок не отображаются (в отличие от других переменных); т.о. можно избежать неудобств от-того, что ссылки часто используются для больших структур. Если только Вы не установили `set print address off', адрес ссылочной переменной всегда выводится. 5. GDB поддерживает оператор C++ определения области видимости имени `::' - Вы можете пользоваться им в ваших выражениях точно так же, как в выражениях вашей программы. Так как области могут быть определены одна в другой, Вы можете по необходимости неоднократно использовать `::'; например, в выражении типа `SCOPE1::SCOPE2::NAME'. GDB также позволяет определить область видимости имени относительно исходных файлов как при C, так и при C++ отладке, (см.Раздел 8.2 [Программные переменные]). - 119 - 9.4.1.4. Значения C и C++, используемые по умолчанию Если Вы разрешаете GDB автоматически установить проверку приналежности типу и диапазону, она отключаются, как только рабочим языком становится C или C++. Это происходит независимо от того, кто (Вы или GDB) устанавливает рабочий язык. Если Вы разрешаете GDB автоматически установить язык, он распознает расширения исходных файлов `.c', `.C' или `.cc', и при вводе кода, скомпилированного из такого файла, GDB устанавит рабочим языком C или C++. См.Раздел 9.1.3 [Распознавание GDB исходного языка]. 9.4.1.5. Проверки принадлежности к типу и диапазону в C и C++ Когда GDB анализирует выражения C или C++, по умолчанию проверки соответствия типов не проводятся. Однако, если Вы подключаете их, GDB считает, что типы двух переменных эквивалентны, если: * Обе переменные структурированы и имеют один и тот же тип (структуры, объединения или перечисления). * Имена типов обеих переменных совпадают или были объявлены эквивалентными через `typedef'. Проверка диапазона, если она подключена, выполняется для математических операций. Индексы массивов не проверяются, так как они часто индексируют указатели, не являющиеся сами по себе массивами. 9.4.1.6. GDB и C Команды `set print union' и `show print union' применяются к типу `union'. При установке `on', любые `union', находящиеся внутри каких-либо `struct' или `class', также выводятся. Иначе они отображаются в виде `{...}'. - 120 - Оператор `@' помогает при отладке динамических массивов, сформированных с помощью указателей и функции захвата памяти. См.Раздел 8.1 [Выражения]. 9.4.1.7. Особенности GDB для C++ Некоторые команды GDB полезны особенно для языка C++, а некоторые специально разработаны для него. Ниже приведено их краткое описание: `breakpoint menus' Когда Вы хотите установить точку останова на перегруженной функции, меню точки останова GDB помогает Вам определить, какое определение функции Вам нужно. См.Раздел 5.1.8 [Меню точек останова]. `rbreak REGEX' Установка точек останова с использованием регулярных выражений полезна для установки точек останова на перегруженных функциях, если они не являются членами специальных классов. См.Раздел 5.1.1 [Установка точек останова]. `catch EXCEPTIONS' `info catch' Отладка обработки исключительных ситуаций C++. См.Раздел 5.1.3 [Точки останова и исключительные ситуации]. `ptype TYPENAME' Вместе с другой информацией для типа TYPENAME, вывести отношения наследования. См.Главу 10 [Исследование таблицы символов]. `set print demangle' `show print demangle' `set print asm-demangle' `show print asm-demangle' Управляют формой вывода идентификаторов C++. См.Раздел 8.7 [Установки вывода]. - 121 - `set print object' `show print object' Управляют выводом типов объектов. См.Раздел 8.7 [Установки вывода]. `set print vtbl' `show print vtbl' Управляют форматом вывода таблиц виртуальных функций. См.Раздел 8.7 [Установки вывода]. `Overloaded symbol names' Вы можете указать конкретное определение перегруженного символа, используя ту же запись, что и для объявления таких символов в C++: наберите `SYMBOL(TYPES)' вместо просто SYMBOL. Вы также можете воспользоваться средствами GDB завершения слова командной строки, чтобы вывести список возможных продолжений или чтобы завершить набор за Вас. См.Раздел 3.2 [Завершение команды]. 9.4.2. Modula-2 Расширения, сделанные в GDB для поддержки Modula-2, обеспечиваются только для GNU компилятора Modula-2 (который разрабатывается в настоящее время). Другие компиляторы Modula-2 в настоящее время не поддерживаются, и попытка отладить исполнимые программы, произведенные ими, скорее всего приведет к ошибке при считывании таблицы символов этой программы. 9.4.2.1. Операторы Операторы должны быть определены на значениях определенных типов. Например, оператор `+' определен на числах, но не на структурах. Операторы часто определяются на группах типов. Для целей Modula-2 поддерживаются следующие определения: * *Integral types* - состоят из `INTEGER' (целые числа), `CARDINAL' (порядковые числа) и их поддиапазонов. - 122 - * *Character types* - состоят из множества `CHAR' и его поддиапазонов. * *Floating-point types* - состоят из `REAL' (вещественные числа). * *Pointer types* - состоят из чего-либо, объявленного как "POINTER TO TYPE". * *Scalar types* - включают все вышеперечисленное. * *Set types* - состоят из типов `SET' и `BITSET'. * *Boolean types* - состоят из `BOOLEAN'. Следующие операторы выполняются и представлены здесь в порядке возрастания приоритета: `,' Разделитель в индексе массива или между аргументами функции. `:=' Присваивание. Переменной VAR присвоить значение VALUE. VAR `:=' VALUE. `<, >' Меньше, больше. Определены на целочисленных типах, типах с плавающей точкой или перечислимых типах. `<=, >=' Не больше, не меньше. Определены на целочисленных типах, типах с плавающей точкой или перечислимых типах. Показывает включение в множественных типах. Приоритет как у `<'. `=, <>, #' Равенство и два способа выражения неравенства; допустимы на скалярных типах. Приоритет как у `<'. В тестовом драйвере GDB для неравенства допустим только `<>', так как `#' конфликтует с - 123 - комментатором пакетных файлов. `IN' Установка принадлежности. Определен на множественных типах и типах их элементов. Приоритет как у `<'. `OR' Дизъюнкция (логическое ИЛИ). Определена на булевских типах. `AND, &' Конъюнкция (логическое И). Определен на булевских типах. `@' Оператор "искусственного массива" GDB (См.Раздел 8.1 [Выражения]). `+, -' Сложение и вычитание на целочисленных типах и типах с плавающей точкой. На множественных типах - объединение и разность. `*' Умножение на целочисленных типах и типах с плавающей точкой. На множественных типах - пересечение. `/' Деление на типах с плавающей точкой. Симметричная разность множеств на множественных типах. Приоритет как у `*'. `DIV, MOD' Целочисленное деление и остаток. Определены на целочисленных типах. Приоритет как у `*'. `-' Унарный минус. Определен для целочисленных и вещественных значений. `^' Разыменование. Определен на типах указателей. - 124 - `NOT' Булевское отрицание (логическое НЕ). Определен на булевских типах. Приоритет как у `^'. `.' Селектор полей `RECORD'. Определен для данных типа `RECORD'. Приоритет как у `^'. `[]' Индексация массива. Определен для данных типа `ARRAY'. Приоритет как у `^'. `()' Список параметров процедуры. Определен на объектах `PROCEDURE'. Приоритет как у `^'. `::, .' Операторы определения области видимости в GDB и Modula-2. Предупреждение: Множества и операции над ними GDB еще не поддерживаeт, так что использование оператора `IN' или операторов `+', `-', `*', `/', `=', `<>', `#', `<=' и `>=' на множествах обрабатывается, как ошибка. 9.4.2.2. Встроенные функции и процедуры Modula-2 также поддерживает несколько встроенных процедур и функций. В их описании используются следующие метапеременные: A Представляет переменную типа `ARRAY'. C Представляет константу или переменную типа `CHAR'. - 125 - I Представляет переменную или константу целочисленного типа. M Представляет идентификатор, принадлежащий множеству. Обычно используется в одной и той же функции с метапеременной S. Тип S должен быть `SET OF MTYPE' (где MTYPE - тип M). N Представляет переменную или константу целочисленного типа или типа с плавающей точкой. R Представляет переменную или константу типа с плавающей точкой. T Представляет тип. V Представляет переменную. X Представляет переменную или константу какого-либо типа. См.пояснение к конкретной функции для получения более подробной информации. Ниже описано, какие значения возвращают встроенные процедуры. `ABS(N)' Возвращает абсолютное значение N. `CAP(C)' Если C - символ нижнего регистра, процедура возвращает эквивалент верхнего регистра, иначе возвращает сам аргумент. `CHR(I)' Возвращает символ, порядковое значение которого - I. - 126 - `DEC(V)' Уменьшает значение переменной V. Возвращает новое значение. `DEC(V,I)' Уменьшает значение переменной V на I. Возвращает новое значение. `EXCL(M,S)' Удаляет элемент M из множества S. Возвращает новое множество. `FLOAT(I)' Возвращает в формате чисел с плавающей точкой эквивалент целого числа I. `HIGH(A)' Возвращает индекс последнего элемента A. `INC(V)' Увеличивает значение переменной V. Возвращает новое значение. `INC(V,I)' Увеличивает значение переменной V на I. Возвращает новое значение. `INCL(M,S)' Добавляет элемент M в множество S, если его там еще нет. Возвращает новое множество. `MAX(T)' Возвращает максимальное значение типа T. `MIN(T)' Возвращает минимальное значение типа T. `ODD(I)' Возвращает булевское значение ИСТИНА (TRUE), если I - нечетное число. - 127 - `ORD(X)' Возвращает порядковое значение параметра. Например, порядковое значение литеры - ее ASCII значение (на машинах, поддерживающих ASCII). X должен принадлежать упорядоченному типу, т.е. целочисленному, литерному или перечислимому. `SIZE(X)' Возвращает размер параметра. X может быть переменной или типом. `TRUNC(R)' Возвращает целую часть R. `VAL(T,I)' Возвращает элемент типа T, порядковое значение которого - I. Предупреждение: Множества и операции над ними GDB еще не поддерживает, так что использование процедур `INCL' и `EXCL' обрабатывается как ошибка. 9.4.2.3. Константы GDB позволяет Вам выражать константы Modula-2 следующими способами: * Целочисленные константы задаются просто последовательностью цифр. Используемая в выражении константа интерпретируется так, чтобы быть совместимой (по типу) с остальной частью выражения. Шестнадцатеричные целые числа определяются окончанием `H', а восьмеричные целые числа - окончанием `B'. * Константы с плавающей точкой задаются, как последовательность цифр, сопровождаемая десятичной точкой и другой последовательностью цифр. Возможно отсутвующий порядок может быть задан в форме `E[+|-]NNN', где `[+|-]NNN' - порядок. Все цифры константы с плавающей точкой должны быть десятичными цифрами. * Литерные константы задаются одиночным символом, окруженным парой подобных кавычек - либо одиночных('), либо двойных ("). Они также - 128 - могут быть заданы своим порядковым значением (обычно ASCII), сопровождаемым `C'. * Строковые константы задаются последовательностью литер,окруженной парой подобных кавычек - либо одиночных('), либо двойных ("). Также допускаются управляющие последовательности в стиле C . (См.Раздел 9.4.1.2 [Константы C и C++] для краткого объяснения управляющих последовательностей.) * Перечислимые константы задаются перечислимым идентификатором. * Булевы константы задаются идентификаторами `TRUE' и `FALSE'. * Константные указатели задаются только целыми числами. * Множественные константы пока не поддерживаются. 9.4.2.4. Установки Modula-2 по умолчанию Если проверка принадлежности типу или диапазону установливается автоматически GDB, то по умолчанию они обе устанавливаются `on', как только рабочим языком становится Modula-2, независимо от того, кто выбрал рабочий язык - Вы или GDB. Если Вы разрешаете GDB выбрать язык автоматически, то при вводе кода, скомпилированного из файла с расширением `.mod', GDB устанавит рабочим языком Modula-2. Для подробностей см.Раздел 9.1.3 [Автоматический выбор языка GDB] 9.4.2.5. Отклонения от стандарта Modula-2 Для упрощения отладки программ Modula-2 было сделано несколько изменений. Прежде всего была ослаблена строгость типов: * В отличие от стандарта Modula-2, константные указатели могут быть сформированы целыми числами, что позволяет вам изменять - 129 - переменные-указатели в течение отладки. (В стандарте Modula-2, исполнительный адрес, содержащийся в переменной-указателе скрыт от Вас; его можно изменить лишь прямым присваиванием значения другой переменной-указателя или выражения, возвращающего указатель). * Управляющие последовательности C могут использоваться в строках и символах, чтобы представить невыводимые символы. GDB выводит строки с этими встроенными управляющими последовательностями. Одиночные невыводимые символы печатаются с помощью формата `CHR ( NNN )'. * Оператор присваивания (":=") возвращает значение правого параметра. * Все встроенные процедуры и изменяют, и возвращают свои параметры. 9.4.2.6. Проверка Modula-2 принадлежности к типу и диапазону Предупреждение: в этой версии GDB не выполняет проверки принадлежности диапазону или типу. GDB рассматривает два типа переменных Modula-2 эквивалентными, если: * Их типы были объявлены эквивалентными посредством утверждения `TYPE T1 = T2' * Они были объявлены на одной и той же строке. (Примечание: Это верно для GNU-компилятора Modula-2, но это может не выполнятся для других компиляторов.) Пока допускается проверка соответствия типов, любая попытка скомбинировать переменные не эквивалентных типов является ошибкой. Проверка диапазона выполняется во всех математических операциях, при присваивании, при индексации массива и во всех встроенных функциях и процедурах. - 130 - 9.4.2.7. Операторы определения области видимости `::' и `.' Имеются несколько тонких различий между оператором Modula-2 `.' и оператором GDB `::'. У обоих похожий синтаксис: MODULE . ID SCOPE :: ID где SCOPE - имя модуля или процедуры, MODULE - имя модуля и ID - любой описанный в пределах вашей программы идентификатор, за исключением другого модуля. Использование оператора `::' заставляет GDB искать идентификатор ID в области действия, определенной SCOPE. Если он не найден в определенной области, GDB ищет его во всех областях действия, видимых из области SCOPE. Использование оператора `.' заставляет GDB искать текущую область действия для идентификатора, определенного ID, который был импортирован из модуля определения, определенного MODULE. Cчитается ошибкой, если идентификатор ID не был импортирован из модуля определения MODULE или если ID не является идентификатором в MODULE. 9.4.2.8. GDB и Modula-2 Некоторые команды GDB мало используются при отладке программ на Modula-2. Пять подкоманд, относящиеся к командам `set print' и `show print', применяются специально к C и C++. Это: `vtbl', `demangle', `asm-demangle', `object' и `union'. Первые четыре применимы к C++, а последняя к типу C `union', который не имеет никакого прямого аналога в Modula-2. Оператор `@' (См.Раздел 8.1 [Выражения]), хоть и доступен при использовании любого языка, бесполезен в работе с Modula-2. Его цель состоит в том, чтобы помочь при отладке динамических массивов, которые не могут быть созданы в Modula-2 также, как в C или C++. Однако конструкция `{TYPE}ADREXP' все же полезна, т.к. адрес может быть - 131 - определен целозначной константой. (См.Раздел 8.1 [Выражения]) В тестовых драйверах GDB, оператор неравенства Modula-2 `#' интерпретируется как начало комментария. Используйте вместо него `<>'. 10. Исследование таблицы символов Команды, описанные в этом разделе, позволят вам получить информацию о символах (именах переменных, функций и типов), определенных в вашей программе. Эта информация присуща вашей программе и не изменяется при ее выполнении. GDB находит ее в таблице символов вашей программы в файле, определенном при запуске GDB (см.Раздел 2.1.1 [Выбор файлов]) или посредством одной из команд управления файлами (см.Раздел 12.1 [Команды для определения файлов]). Иногда Вы можете нуждаться в ссылке на символы, содержащие литеры, которые GDB обычно трактует как разделители слов. Наиболее часто встречается ссылки на статические переменные в другом исходном файле (см.Раздел 8.2 [Программные переменные]). Имена файлов записаны в объектных файлах как отладочные символы, но GDB обычно разбирает имя файла, например, 'foo.c', как три слова 'foo' '.' 'c'. Чтобы GDB идентифицировал 'foo.c' как одно слово, заключите его в двойные кавычки; например, p 'foo.c'::x проверить значение `x' в пределах файла 'foo.c'. `info address SYMBOL' Определяет, где храняться данные для SYMBOL. Для регистровой переменной сообщается, в каком регистре они содержатся. Для нерегистровой локальной переменной печатается смещение в процедурной секции, по которому переменная всегда хранится. Эта команда отличается от команды 'print &SYMBOL', которая вообще не работает с регистровыми переменными, а для стековых локальных переменных печатает точный адрес переменной в настоящий момент. - 132 - `whatis EXP' Выводит тип выражения EXP. На самом деле EXP не вычисляется, а присутствующие в нем побочные эффекты (такие, как присваивания или вызовы функций) не проявляются. См.Раздел 8.1 [Выражения]. `whatis' Выводит тип `$' (последнего значения в архиве значений). `ptype TYPENAME' Выводит описание типа данных TYPENAME. TYPENAME может быть именем типа или (для C-кода) может иметь форму `class CLASS-NAME', `struct STRUCT-TAG', `union UNION-TAG' или `enum ENUM-TAG'. `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' без параметра ссылается на тип `$' - последнего значения в архиве значений. - 133 - `info types REGEXP' `info types' Выводит краткое описание всех типов, имена которых соответствуют REGEXP (или всех типов в вашей программе, если вы используете команду без параметра). Каждое полное имя типа рассматривается как полная стpока; таким образом, `i type value' выдает инфомацию обо всех типах в вашей пpогpамме, имена которых включают стpоку `value', а `i type ^value$' выдает инфоpмацию только о типах с полным именем `value'. Эта команда отличается от `ptype': во-пеpвых, она, как и `whatis', не выводит детализированное описание; во-втоpых, она пpосматpивает все исходные файлы, где тип опpеделен. `info source' Показывает имя текущего исходного файла - файла функции, содеpжащей текущую точку выполнения - и язык, на котоpом он написан. `info sources' Выводит имена всех исходных файлов вашей пpогpаммы, для котоpых имеется отладочная инфоpмация, оpганизуя их в два списка: файлы с уже прочитанными символами, и файлы, символы которых будут пpочитаны, когда потpебуется. `info functions' Выводит имена и типы данных всех опpеделенных функций. `info functions REGEXP' Выводит имена и типы данных всех опpеделенных функций, имена которых содеpжат выpажение REGEXP. Так, 'info fun step' находит все функции, имена которых включают в себя `step'; 'info fun ^step' - функции с именами, начинающимися со `step'. `info variables' Выводит имена и типы всех пеpеменных, объявленных вне функций (т.е. локальные пеpеменные исключаются). - 134 - `info variables REGEXP' Выводит имена и типы всех пеpеменных (кpоме локальных), имена котоpых содеpжат выpажение REGEXP. Некотоpые системы допускают использование индивидуальных объектных файлов, что позволяет пеpеместить вашу пpогpамму без остановки и перезапуска пpогpаммы. Напpимеp, в VxWorks вы можете пpосто пеpекомпилиpовать дефектный объектный файл и пpодолжить выполнение. Если вы pаботаете в одной из таких систем, GDB может пеpезагpузить символы для автоматически подключаемых модулей: `set symbol-reloading on' Пеpеместить опеделения символов в соответствующий исходный файл, когда объектный файл с таким именем встpетится снова. `set symbol-reloading off' Не пеpемещать опpеделения символов пpи новой встpече файла с таким именем. Устанавливается по умолчанию; если вы pаботаете в системе, не позволяющей автоматическое пеpеподключение модулей, вы не должны использовать `symbol-reloading off', т.к. иначе GDB может сбpосить символы пpи подключении больших пpогpамм, котоpые могут содеpжать несколько модулей (из нескльких каталогов или библиотек) с тем же именем. `show symbol-reloading' Показывает текущую установку `on' или `off'. `maint print symbols FILENAME' `maint print psymbols FILENAME' `maint print msymbols FILENAME' Записывает дамп данных отладочных символов в файл FILENAME. Эти команды используются для отладки GDB-кода посимвольного чтения. Включаются только символы с отладочными данными.Если вы используете `maint print symbols', GDB включает все символы, для котоpых уже собpана полная информация: т.е. FILENAME отpажает символы только тех файлов, символы которых GDB уже пpочитал. Вы можете использовать команду `info sources', чтобы опpеделить, - 135 - какие это файлы. Если вы используете `maint print psymbols', дамп показывает инфоpмацию о символах, котоpая GDB известна частично, т.е. символы опpеделены в файлах, котоpые GDB только пpосмотpел, но не пpочитал полностью. Наконец, `maint print msymbols', собиpает только минимальную инфоpмацию, тpебуемую для каждого объектного файла, из котоpого GDB пpочитал несколько символов. См.Раздел 12.1 [Команды для определения файлов], для большей информации о чтении символов (в описании `symbol-file'). 11. Выполнение с изменениями в программе Если Вы нашли ошибку в своей пpогpамме и хотите выяснить навеpняка, пpиведет ли испpавление кажущейся ошибки к веpному выполнению всей пpогpаммы, Вы можете воспользоваться средствами GDB выполнения с изменениями в программе. Напpимеp, Вы можете сохpанить новые значения в пеpеменных или ячейках памяти, подать своей пpогpамме сигнал, осуществить перезапуск с дpугого адpеса или даже пpеждевременно выйти из функции. 11.1. Присваивание значений пеpеменным Для изменения значения пеpеменных используйте выpажение присваивания. См.Раздел 8.1 [Выpажения]. Напpимеp, print x=4 сохpаняет значение 4 в пеpеменной `x' и затем выводит значение данного выpажения (pавное 4). См.Главу 9 [GDB и различные языки программирования], для получения большей инфоpмации об опеpатоpах поддеpживаемых языков. Если вывод значения выpыжения не является необходимым, используйте команду `set' вместо `print'. Команда `set' аналогична команде `print' за исключением того, что значение выpажения не выводится и не записывается в аpхив значений (см.Раздел 8.8 [Аpхив значений]). - 136 - Если в начале стpоки параметров команды `set' появляется идентичная `set' подкоманда, используйте команду `set variable' вместо пpосто `set'. Эта команда идентична `set', но не имеет подкоманд. Напpимеp, если в вашей пpогpамме есть пеpеменная `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. Недопустимое выpажение, конечно, '=47'. Чтобы действительно установить пpогpаммную пеpеменную `width', используйте (gdb) set var width=47 GDB допускает такие присваивания, какие в C недопустимы; Вы можете сохpанять целое значение в пеpеменной-указателе и наоборот, преобразовать любую стpуктуpу к дpугой стpуктуpе той же длины или меньшей. Для сохpанения значения определенного типа в пpоизвольном месте памяти, используйте констpукцию `{...}' (см.Раздел 8.1 [Выpажения]). Напpимеp, {int}0x83040 ссылается на ячейку памяти 0x83040 как на содержащую целое (котоpое пpедполагает соответствующий pазмеp и пpедставление в памяти), и set {int}0x83040 = 4 записывает значение 4 в эту ячейку. - 137 - 11.2. Продолжение выполнения с другого адреса Обычно, когда Вы продолжаете выполнение программы, оно продолжается с того места, где остановилось, с помощью команды `continue'. Вместо этого Вы можете продолжить выполнение с выбранного адреса посредством следующих команд: `jump LINESPEC' Возобовление выполнения со строки LINESPEC. Если там есть точка останова, выполнение немедленно прекращается. См.Раздел 7.1 [Вывод строк исходного текста], для получения информации о различных формах LINESPEC. Команда `jump' не изменяет ни текущую процедурную секцию, ни указатель стека, ни содержимое ячеек памяти или регистров, кроме PC. Если строка LINESPEC находится не в функции, выполняющейся в настоящее время, результаты могут быть неожиданными, если две функции используют аргументы или локальные параменные разных типов. По этой причине команда `jump' запрашивает подтверждение, если определяемая строка находится не в функции, выполняющейся в настоящее время. Однако, даже неожиданные результаты предсказуемы, если Вы хорошо ознакомлены с машинным кодом вашей программы. `jump *ADDRESS' Возобновление выполнения с адреса ADDRESS. Вы можете достичь аналогичного результата установкой нового значения в регистре `$pc'. Отличие в том, что она не начинает выполнение вашей программы; она только изменяет адрес, с которого *будет* выполняться программа, когда Вы продолжите выполнение. Например, set $pc = 0x485 заставляет следующую команду `continue' или команду пошагового выполнения выполнять программу с адреса `0x485', а не с адреса, где ваша прграмма остановилась. См.Раздел 5.2 [Продолжение исполнения и - 138 - пошаговое выполнение]. Наиболее общий случай использования команды `jump' состоит в возвращении к выполнению, возможно уже с большим количеством точек останова, части программы, которая уже выполнялась, чтобы исследовать ее выполнение более детально. 11.3. Подача сигнала вашей программе `signal SIGNAL' Возобновляет выполнение при остановке программы, но немедленно выдает ей сигнал SIGNAL. SIGNAL может быть именем или номером сигнала. Например, во многих системах `signal 2' и `signal SIGINT' - два способа подать сигнал прерывания. Наоборот, если SIGNAL - нуль, выполнение продолжается без выдачи сигнала. Это полезно, если ваша программа остановлена из-за сигнала; она получит сигнал при возобновлении выполнения командой `continue'; `signal 0' заставит продолжать выполнение без сигнала. `signal' не повторяется, когда Вы нажимаете RET после выполнения команды. Вызов команды `signal' отличается от вызова утилиты `kill' из оболочки. Подача сигнала посредством `kill' заставляет GDB решать, что делать с сигналом, в зависимости от таблиц обработки сигналов (см.Раздел 5.3 [Сигналы]). Команда `signal' передает сигнал прямо в программу. - 139 - 11.4. Возврат из функции `return' `return EXPRESSION' Вы можете отменить выполнение функции с помощью команды `return'. Если Вы задаете параметр EXPRESSION, его значение используется как значение, возвращаемое функцией. Когда Вы используете `return', GDB сбрасывает выбранную процедурную секцию (и все секции внутри нее). Вы можете считать это преждевременным возвратом из сброшенной секции. Если Вы желаете определить возвращаемое значение, задайте это значение параметром `return'. Команда `return' выталкивает выбранную процедурную секцию (см.Раздел 6.3 [Выбор процедурной секции]) и все секции внутри нее. Процедурная секции, вызвавшая выбранную, становится внутренней и считается выбранной. Возвращаемое значение сохраняется в регистрах, используемых для возврата значений функций. Команда `return' не возобновляет выполнение; она оставляет программу остановленной в том состоянии, в котором бы она была сразу при возврате из функции. Напротив, команда `finish' (см.Раздел 5.2 [Продолжение исполнения и пошаговое выполнение]) возобновляет выполнение до естественного возврата из выбранной процедурной секции. 11.5. Вызов функций программы `call EXPR' Вычислить выражение EXPR без отображения возвращаемых значений `void'. Вы можете использовать этот вариант команды `print', если хотите выполнить функцию из вашей программы без ненужного вывода возвращаемых значений `void'. Если результат не `void', он выводится и сохраняется в архиве значений. - 140 - CALL_SCRATCH_ADDRESS - новая переменная, управляемая пользователем. Она определяет местоположение рабочей области, используемой, когда GDB вызывает функцию на целевой машине. Это необходимо, так как обычный метод помещения рабочей области в стек, не работает в системах с раздельными областями команд и данных. 11.6. Внесение изменений в программу По умолчанию 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' Показывает, открыты ли исполняемые файлы (или дампы памяти) для записи. - 141 - 12. Файлы GDB GDB должен знать имя файла, который будет отлаживаться, чтобы прочитать его таблицу символов и запустить вашу программу. Для обработки дампа памяти от предыдущего выполнения, Вы также должны сообщить GDB его имя. 12.1. Команды для определения файлов Определение имени исполняемого файла или имени файла дампа памяти обычно делается во время запуска GDB, используя соответствующие параметры команды запуска GDB (см.Главу 2 [Вход и выход из GDB]). Иногда необходимо выбрать во время сеанса GDB другой файл для работы. Или при запуске GDB Вы можете забыть определить файл, который Вы хотите использовать. В такой ситуации полезны команды для определения новых файлов. `file FILENAME' Использовать FILENAME в качестве программы, которая будет отлаживаться. Из нее читаются символы и содержание неизменяемой памяти. При использовании команды `run' будет выполняться именно эта программа. Если Вы не определили каталог, и файл не найден в рабочем котологе GDB, GDB использует переменную окружения `PATH' в качестве списка каталогов для поиска, так же, как это делает оболочка, когда ищет программу для выполнения. Вы можете изменить значение этой переменной и для GDB, и для вашей программы, используя команду `path'. В системах с доступом к области памяти посредством механизма доступа к файлу таблица символов может содержаться во вспомогательном файле `FILENAME.syms'. Если файл существует, GDB читает таблицу символов из `FILENAME.syms', запускаясь быстрее. См.описание опций `-mapped' и `-readnow' (допустимых в командной строке и в командах `file', `symbol-file' или `add-symbol-file', описанных ниже) для получения большей информации. - 142 - `file' `file' без параметров заставляет GDB сбросить любую имеющуюся информацию об исполняемом файле и о таблице символов. `exec-file [ FILENAME ]' Определяет, что программа, которая должна быть выполнена, но не таблица символов, находится в FILENAME. С помощью переменной окружения `PATH' GDB, если это необходимо, ищет путь к вашей программе. Отсутствие параметра FILENAME приводит к сбросу информации об исполняемом файле. `symbol-file [ FILENAME ]' Читает таблицу символов из файла FILENAME. По необходимости используется переменная окружения `PATH'. Если таблица символов и исполняемая программа находятся в одном файле используйте команду `file'. `symbol-file' без параметров сбрасывает информацию GDB о таблице символов вашей программы. Команда `symbol-file' заставляет GDB забыть рабочие переменные, содержание архива значений и все точки останова и выражения автоматического отображения, т.к. они могут содержать указатели на внутренние данные записи символов и типы данных, которые являются частью данных старой таблицы символов, сбрасываемой GDB. `symbol-file' не повторяется нажатием RET. Когда GDB сконфигурирован для определенной среды, он распознает отладочную информацию в стандартном формате, который генерируется для этой среды; Вы можете использовать GNU-компилятор или другие компиляторы, которые придерживаются местных соглашений. Наилучшие результаты обычно достигаются с помощью GNU-компилятора; например, используя `gcc', Вы можете генерировать отладочную информацию для оптимизированного кода. Для некоторых видов объектных файлов по команде `symbol-file' таблица символов обычно не читается сразу полностью. Вместо этого - 143 - таблица символов быстро сканируется для определения, какие исходные файлы и символы в ней присутствуют. Детали читаются позже, по мере необходимости. Такое двухстадийное чтение используется для того, чтобы заставить GDB запускаться быстрее. Его действие практически незаметно, за исключением пауз при чтении деталей таблицы символов конкретного исходного файла. (Команда `set verbose' позволяет во время этих пауз выводить сообщения, если это желательно. См.Раздел 14.6 [Необязательные предупреждения и сообщения]). Двухступенчатое чтение для COFF еще не реализовано. Если таблица символов сохранена в формате COFF, `symbol-file' читает данные таблицы символов сразу полностью. `symbol-file FILENAME [ -readnow ] [ -mapped ]' `file FILENAME [ -readnow ] [-mapped ]' Если Вы хотите, чтобы вся таблица символов была доступна GDB, Вы можете отменить двухступенчатое чтение таблицы символов GDB, используя опцию `-readnow' с любой командой, загружающей таблицу символов. Если доступ к области памяти посредством механизма доступа к файлу осуществляется вашей системе через системный вызов `mmap', Вы можете использовать другую опцию, `-mapped', чтобы заставить GDB записывать символы вашей программы в файл многократного использования. Последующие сеансы отладки GDB отображают информацию о символах из этого вспомогательного символьного файла (если программа не изменялась), вместо того, чтобы тратить время на чтение таблицы символов из исполняемой программы. Использование опции `-mapped' производит такой же эффект, как запуск GDB с опцией `-mapped' командной строки. Вы можете использовать обе опции вместе, чтобы быть уверенным, что во вспомогательном символьном файле содержится вся информация о символах вашей программы. - 144 - Вспомогательный символьный файл для программы MYPROG называется `MYPROG.syms'. Если этот файл существует (и создан раньше, чем соответствующая исполняемая программа), GDB пытается использовать его, когда Вы отлаживаете MYPROG; не требуется никаких специальных опций или команд. Для главной машины, на которой запускается GDB, `.syms' файл - особый. Он содержит точное отображение внутренней таблицы символов GDB и не может быть разделен между несколькими главными платформами. `core-file [ FILENAME ]' Определяет, какой использовать. Обычно файлы дампов памяти содержат только некоторые части адресного пространства процесса; GDB может самостоятельно обращаться за другими частями к исполнимому файлу. `core-file' без параметра указывает, что файл дампирования не используется. Обратите внимание, что файл дампа игнорируется, если в данное время ваша программа выполняется под управлением GDB. Так что, если Вы запустили вашу программу и желаете вместо этого отлаживать некий файл дампа, Вы должны уничтожить подпроцесс, в котором выполняется ваша программа. Для этого используйте команду `kill' (см.Раздел 4.8 [Уничтожение порожденного процесса]). `load FILENAME' Команда `load' может быть доступна в зависимости от того, какие средства удаленной отладки сконфигурированы в GDB. Эта команда, если она поддерживается, делает исполнимый файл FILENAME доступным для отладки на удаленной системе - например, посредством выгрузки или динамического подключения. Команда `load' также загружает таблицу символов файла FILENAME в GDB, подобно команде `add-symbol-file'. Если ваша версия GDB не допускает команды `load', то при попытке выполнить ее Вы получите сообщение об ошибке: "`You can't do that - 145 - when your target is ...'" Файл загружается по любому адресу, указанному в исполнимом файле. Для некоторых форматов объектных файлов Вы можете определить адрес загрузки при компоновке программы; для других форматов, таких как a.out, формат объектного файла определяет фиксированный адрес. В VxWorks, команда `load' подключает FILENAME динамически в текущую целевую систему и добавляет его символы в GDB. С интерфейсом Nindy на плате Intel 960, команда `load' выгружает FILENAME на 960 и добавляет его символы в GDB. Когда Вы выбираете удаленную отладку на плате Hitachi SH, H8/300 или H8/500 (см.Раздел 13.4.7 [GDB и микропроцессоры Hitachi]), команда `load' загружает вашу программу на плату Hitachi, а также открывает ее, как текущую исполняемую цель для GDB на вашей головной машине (как команда 'file'). Команда `load' не повторяется при повторном нажатии клавиши RET. `add-symbol-file FILENAME ADDRESS' `add-symbol-file FILENAME ADDRESS [ -readnow] [ -mapped ]' Команда `add-symbol-file' читает дополнительную информацию таблицы символов из файла FILENAME. Эту команду следует использовать, когда FILENAME был динамически загружен (некими другими средствами) в исполняющуюся программу. ADDRESS должен быть адресом памяти, по которому файл загружен - GDB не может сформировать его самостоятельно. Вы можете определить адрес как выражение. Таблица символов файла FILENAME добавляется к таблице символов, прочитанной первоначально командой `symbol-file'. Вы можете использовать команду `add-symbol-file' любое число раз; новые символьные данные продолжают добавляться к старым. Чтобы сбросить все старые символьные данные, используйте команду `symbol-file'. - 146 - Команда `add-symbol-file' не повторяется при повторном нажатии клавиши RET. Вы можете использовать опции `-mapped' и `-readnow' также, как для команды `symbol-file'. `add-shared-symbol-file' Команда `add-shared-symbol-file' может быть использована только под управлением операционной системы Harris' CXUX для Motorola 88k. GDB автоматически ищет разделяемые библиотеки, но если он не найдет вашу, Вы можете запустить `add-shared-symbol-file'. Она не имеет параметров. `section' Команда `section' изменяет базовый адрес раздела SECTION исполняемого файла на ADDR. Она может использоваться, если исполняемый файл не содержит адресов разделов (как в формате a.out) или когда адреса, определенные непосредственно в файле, неверны. Каждый раздел должен быть изменен отдельно. Команда `info files' выводит список всех разделов и их адресов. `info files' `info target' `info files' и `info target' - синонимы; обе печатают текущую цель (см.Главу 13 [Определение отладочной цели]), включая имена исполняемого файла и файла дампов памяти файлов, используемых в данный момент GDB, а также файлов, из которых были загружены символьные таблицы. Команда `help target' выводит список не текущих, а всех возможных целей. Все команды определения файлов допускают и абсолютные, и относительные имена в качестве параметров. GDB всегда преобразовывает имя файла в абсолютное имя файла и запоминает путь. Для SunOS, SVr4, Irix 5 и IBM RS/6000 GDB поддерживает разделяемые библиотеки. GDB автоматически загружает определения символов из разделяемых библиотек, когда Вы используете команду `run' или когда Вы - 147 - исследуете файл дампа памяти. До использования вами команды `run' GDB не понимает ссылок на функции из разделяемых библиотек, если только Вы не работаете с файлом дампа. `info share' `info sharedlibrary' Выводит имена разделяемых библиотек, которые в данный момент загружены. `sharedlibrary REGEX' `share REGEX' Загружает символы разделяемой объектной библиотеки для файлов, соответсвующих регулярному выражению Unix. Как с автоматически загружаемыми файлами, она загружает только разделяемые библиотеки, требуемые вашей программой для выбранного файла дампа или после набора `run'. Если REGEX опущено, загружаются все требуемые вашей программой разделяемые библиотеки. 12.2. Ошибки чтения символьных файлов При чтении символьного файла GDB иногда сталкивается с такой проблемой, как не распознавание типов символов или известные ошибки вывода транслятора. По умолчанию GDB не сообщает вам о таких проблемах, так как они сравнительно общие и прежде всего представляют интерес для людей, отлаживающих трансляторы. Если вам интересна информация о плохо созданных таблицах символов, Вы можете попросить GDB напечатать только одно сообщение по каждому типу проблем, независимо от того, сколько раз проблема встречалась; или Вы можете попросить GDB напечатать больше сообщений, чтобы увидеть, сколько раз проблема встречалась, командой `set complaints' (см.Раздел 14.6 [Необязательные предупреждения и сообщения]). Текущие печатаемые сообщения и их значения, включают: `inner block not inside outer block in SYMBOL' Ошибочна символьная информация указывающая на начало и конец области видимости (тела функций или блоки операторов). Данная - 148 - ошибка указывает, что некоторый внутрений блок описаний не полностью содержится в его внешнем блоке описаний. GDB обходит проблему, считая далее, что внутренний блок имеет такую же область видимостм, что и внешний блок. Если внешний блок не является функцией, в данном сообщении SYMBOL может быть показан как "`(don't known)'". `block at ADDRESS out of order' Символьная информация для блоков символьных областей должна находиться по увеличивающимся адресам. Ошибка указывает, что это не так. GDB не обходит эту проблему и имеет трудности в определении местоположения символов в исходном файле, символы которого читаются. (Часто Вы можете определить имя породившего проблему исходного файла при помощи определения `set verbose on'. (См.Раздел 14.6 [Необязательные предупреждения и сообщения]) `bad block start address patched' Символьная информация для блоков символьных областей имеет начальный адрес, меньший, чем адрес предшествующей исходной строки. Это, как известно, происходит в трансляторе Си SunOS 4.1.1 (и более ранних). GDB обходит проблему, обрабатывая блок символьной области как начинающийся с предыдущей исходной строки. `bad string table offset in symbol N' Идентификатор N содержит указатель на строковую таблицу, большую чем размер строковой таблицы. GDB обходит проблему, полагая, что символ имеет имя `foo',что может вызвать другие проблемы, если несколько символов заканчиваются этим именем. - 149 - `unknown symbol type `0xNN'' Символьная информация содержит новые типы данных, которые GDB еще не знает, как читать. `0xNN' - тип символа неверно истолкованной информации, в шестнадцатеричном виде. GDB обходит ошибку, игнорируя эту символьную информацию. Это обычно позволяет отладживать вашу программу, хотя некоторые символы и недоступны. Если Вы сталкиваетесь с такой проблемой и желаете отладить ее, Вы можете запустить под отладчиком сам `gdb', установив точку останова на `complain', и затем дойти до функции `read_dbx_symtab' и проверить `*bufp', чтобы проанализировать эту символьную информацию. `stub type has NULL name' GDB не может найти полное определение для структуры или класса. `const/volatile indicator missing (ok if using g++ v1.x), got...' В символьной информации элемента функции Си++ пропущена информация, которую текущая версия транслятора должна вывести для нее. `info mismatch between compiler and debugger' GDB не может разобрать тип спецификации, выводимой транслятором. 13. Определение отладочной цели "Цель" - это исполняющая среда, занятая вашей программой. Часто GDB запускается в той же самой головной среде, что и ваша программа; в этом случае отладочная цель задается неявно в момента использования команд `file' или `core'. Когда вам нужна большая гибкость - например, запуск GDB на физически отделенной головной машине или управление автономной системой последовательным портом или системой реального времени соединением TCP/IP - вы можете использовать команду `target' для определения одного из целевых типов, сконфигурированных для GDB (см.Раздел 13.2 [Команды управления целями]). - 150 - 13.1. Активные цели Существует три класса целей: процессы, файлы дампов памяти и исполняемые файлы. GDB может обрабатывать одновременно до трех активных целей, по одной каждого класса. Это позволяет вам (например) запустить процесс и проверять его действия без отказа от работы над файлом дампа. Например, если Вы выполняете `gdb a.out', то исполняемый файл `a.out' является единственной активной целью. Если Вы обозначите также файл дампа (возможно от предыдущего выполнения этой же программы), тогда GDB имеет две активные цели и использует их тандемно, рассматривая сначала файл дампа, а затем исполняемого файла по запрошенным адресам памяти. Обычно эти два типа целей дополняют друг друга, так как файл дампа памяти содержит только программную память (переменные и т.п.) и машинное состояние, в то время как исполняемый файл содержит только текст программы и инициализированные данные. Когда Вы набираете `run', ваш исполняемый файл становится активной целью процесса. Когда цель процесса активна, все команды GDB, запрашивающие адреса памяти, относятся к этой цели; адреса активной цели основного файла или исполняемого файла неизвестны, пока активна цель процесса. Используйте команды `core-file' и `exec-file' для выбора нового файла дампа памяти или исполнительного файла (см.Раздел 12.1 [Команды для определения файлов]). Для определения в качестве цели процесса,который уже выполняется, используйте команду `attach' (см.Раздел 4.7 [Отлаживание запущенного процесса]). - 151 - 13.2. Команды управления целями `target TYPE PARAMETERS' Соединяет головную среду GDB с целевой машиной или процессом. Цель - обычно протокол для общения со средствами отладки. Параметр TYPE используется, чтобы определить тип или протокол целевой машины. Дальнейшие параметры PARAMETERS интерпретируются в соответствии с целевым протоколом, но обычно включают такие вещи, как имена устройств или имена базовых машин, с которыми осуществляется связь, номера процессов и скорости в бодах. Команда `target' не повторяется при повторном нажатии RET после выполнения команды. `help target' Отображает имена всех доступных целей. Чтобы отобразить цели, выбранные в данный момент, используйте `info target' или `info files' (см.Раздел 12.1 [Команды для определения файлов]). `help target NAME' Описывает определенную цель, включая любые необходимые для ее выбора параметры. `set gnutarget ARGS' GDB использует свою собственную библиотеку для чтения ваших файлов. GDB знает, читает ли она файл дампа, исполняемый или объектный файл, однако вы можете определить формат файла командой `set gnutarget'. В отличии от большинства команд `target', `target' в `gnutarget' относится к программе, а не к машине. *Предупреждение:* Для определения формата файла посредством `set gnutarget' вы должны знать фактическое имя BFD. См.Раздел 12.1 [Команды для определения файлов]. - 152 - `show gnutarget' Используйте команду `show gnutarget' для отображения, какой формат файла `gnutarget' установлен для чтения. Если вы не установили `gnutarget', GDB определит формат для каждого файла автоматически, и `show gnutarget' выведет `The current BFD target is "auto"'. Ниже приведены некоторые общие цели (доступные или нет, в зависимоси от конфигурации GDB): `target exec PROGRAM' Исполняемый файл. `target exec PROGRAM' - то же самое, что и `exec- file PROGRAM'. `target core FILENAME' Файл дампа памяти. `target core FILENAME' - то же самое, что и `core-file FILENAME'. `target remote DEV' Определяет удаленную цель со специальным последовательным GDB-протоколом. Параметр DEV определяет, какое последовательное устройство используется для соединения (например, `/dev/ttya'). См.Раздел 13.4 [Дистанционная отладка]. Сейчас `target remote' поддерживает команду `load'. Это полезно, только если вы можете получить заглушку для целевой системы каким-нибудь другим способом и можете разместить ее в памяти, где она не будет затерта при загрузке. `target sim' Имитатор ЦП. См.Раздел 13.4.9 [Целевой имитируемый ЦП]. `target udi KEYWORD' Отдаленная цель AMD29K, использующая протокол AMD UDI. Параметр KEYWORD определяет, какая 29K плата или имитатор используется. См.Раздел 13.4.3 [UDI-протокол для AMD29K]. - 153 - `target amd-eb DEV SPEED PROG' Отдаленный PC-резидент платы AMD EB29K, подключенной к последовательной линии. DEV - последовательное устройство, как для `target remote'; SPEED позволяет определить скорость линии связи(linespeed); и PROG - имя отлаживаемой программы, как оно обозначено в DOS на PC. См.Раздел 13.4.4 [EBMON-протокол для AMD29K]. `target hms DEV' Плата Hitachi SH, H8/300 или H8/500, подключенная через последовательную линию к вашей головной машине. Используйте специальные команды `device' и `speed' для управления последовательной линией и используемой скоростью связи. См.Раздел 13.4.7 [GDB и микропроцессоры Hitachi]. `target nindy DEVICENAME' Плата Intel 960, управляемая монитором Nindy. DEVICENAME - имя последовательного устройства, используемого для соединения, например, `/dev/ttya'. См.Раздел 13.4.2 [GDB с удаленным i960 (Nindy)]. `target st2000 DEV SPEED' Телефонное подключение(phone switch) через устройство Tandem ST2000, использующее протокол STDBUG фирмы Tandem. DEV - имя устройства, подключенного к последовательной линии ST2000; SPEED - скорость линии связи. Параметры не используются, если GDB сконфигурирован для соединения с ST200 с использованием TCP или Telnet. См.Раздел 13.4.5 [GDB с Tandem ST2000]. `target vxworks MACHINENAME' Система VxWorks, подключенная через TCP/IP. Параметр MACHINENAME - имя машины целевой системы или адрес IP. См.Раздел 13.4.6 [GDB и VxWorks]. `target cpu32bug DEV' Монитор CPU32BUG, выполняющийся на плате CPU32 (M68K). - 154 - `target op50n DEV' Монитор OP50N, выполняющийся на плате OKI HPPA. `target w89k DEV' Монитор W89K, выполняющийся на плате Winbond HPPA. `target est DEV' Монитор EST-300 ICE, выполняющийся на плате CPU32 (M68K). `target rom68k DEV' Монитор ROM 68K, выполняющийся на плате IDP. `target array DEV' Array Tech LSI33K RAID контролируемая плата. `target sparclite DEV' Платы Fujitsu sparclite, используемые только с целью загрузки. Вы должны использовать дополнительную команду для отладки программы. Например: `target remote DEV', использующую стандартный удаленный протокол GDB. Различные цели доступны на различных конфигурациях GDB; ваша конфигурация может иметь большее или меньшее количество целей. 13.3. Выбор целевого порядка байтов Теперь вы можете выбрать, какой порядок байтов будет использоваться в целевой системе. Используйте команды `set endian big' и `set endian little'. Используйте команду `set endian auto' для указания GDB использовать порядок байт, связанный с исполняемой программой. Вы можете посмотреть текущую установку порядка байтов командой `show endian'. *Предупреждение:* В настоящее время только встроенные MIPS конфигурации поддерживают динамический выбор целевого порядка байтов. - 155 - 13.4. Дистанционная отладка Если вы пытаетесь отлаживать программу, выполняемую на машине, которая не может запустить GDB обычным способом, часто бывает полезна дистанционная отладка. Например, вы можете использовать дистанционную отладку в ядре операционной системы или в малой системе, которая не имеет достаточно мощной операционной системы общего назначения для запуска отладчика со всеми возможностями. Некоторые конфигурации GDB имеют специальный последовательый или TCP/IP интерфейс для работы с частными отладочными целями. Дополнительно GDB поступает с общим последовательным протоколом (специфическим для GDB, но не для любой частной целевой системы), который вы можете использовать, если напишете удаленные заглушки--код, выполняемый в удаленной системе для связи с GDB. В вашей конфигурации GDB могут быть доступны другие отделенные цели; используете `help target' для их перечисления. 13.4.1. Отдаленный последовательный протокол GDB Для отладки программы, выполняемой на другой машине (отладочной "целевой" машине), вы сперва должны организовать все обычные предпосылки для выполнения программы. Например, для программы Си вам нужны: 1. Процедура запуска для установления среды выполнения Си; они обычно имеют имя, подобное `crt0'. Процедура запуска может быть обеспечена вашими аппаратными средствами, или вы должны будете написать свою собственную. 2. Вам, вероятно, понадобится библиотека подпрограмм Си для поддержки вызовов подпрограмм вашей программой, особенно для управления вводом и выводом. - 156 - 3. Способ установки вашей программы на другой машине--например, программа загрузки. Они часто обеспечиваются поставщиками аппаратных средств, но вам, может, придется написать вашу собственную из документации к аппаратному обеспечению. Следующим шагом будет принятие мер по использованию вашей программой последовательного порта или по связи с машиной, где выполняется GDB ("головной" машиной). В общих чертах схема выглядит следующим образом: *На головной машине,* GDB уже понимает, как используется этот протокол; когда устанавливается что-нибудь еще, вы можете просто использовать команду `target remote' ( см.Главу 13 [Определение отладочной цели]). *На целевой машине,* вы должны связать с вашей программой несколько подпрограмм особого назначения, которые выполняют удаленный последовательный протокол GDB. Файл, содержащий эти подпрограммы, называется "отладочной заглушкой". На некоторых удаленных целях вы можете использовать вспомогательную программу `gdbserver' вместо связывания заглушки с вашей программой. См. Раздел 13.4.1.5 [Использование программы `gdbserver'] для детального изучения. Отладочная заглушка специфицирована на архитектуру удаленной машины; например, используйте `sparc-stub.c' для отладки программ на платах SPARC. Следующие рабочие удаленные заглушки распространяются с GDB: `sparc-stub.c' Для архитектур SPARC. `m68k-stub.c' Для архитектур Motorola 680x0. - 157 - `i386-stub.c' Для Intel 386 и совместимых архитектур. В файле `README' дистрибутивов GDB могут перечисляться другие недавно добавленные заглушки. 13.4.1.1. Что заглушка может сделать для Вас Отладочная заглушка для вашей архитектуры обеспечивает следующие три подпрограммы: `set_debug_traps' Эта подпрограмма организует выполнение `handle_exception', когда ваша программа останавливается. Вы должны вызвать эту программу непосредственно перед началом вашей программы. `handle_exception' Это - центральное рабочее средство, но ваша программа никогда не вызывает его явно - установочный код организует запуск `handle_exception', когда вызывается ловушка. `handle_exception' получает управление, когда ваша программа останавливается во время выполнения (например, на точке останова), и требует связи с GDB на головной машине. В ней выполняется протокол связи; `handle_exception' действует, как представитель GDB на целевой машине; она начинается посылкой итоговой информации о состоянии вашей программы, затем продолжает выполняться, отыскивая и передавая любую информацию, требующуюся GDB, пока вы не выполните команду GDB, которая возобновит выполнение вашей программы; в этом месте `handle_exception' возвращает управление вашему коду на целевой машине. `breakpoint' Используйте эту вспомогательную подпрограмму для установки в вашей программе точек останова. В зависимости от конкретной ситуации этот путь может быть единственным способом получения - 158 - управления GDB. Например, если ваша целевая машина имеет несколько видов клавиш прерывания, вам не нужно вызывать ее; нажатие клавиши прарывания передаст управление `handle_exception'--в действительности, GDB. На некоторых машинах простое получение символов последовательным портом может также вызвать ловушку; и снова, в этой ситуации, вам не нужно вызывать `breakpoint' из вашей программы--простое выполнение `target remote' из головного сеанса GDB передаст управление. Вызывайте `breakpoint', если ни одно из этих предположений не верно или вы просто хотите быть уверенным, что ваша программа остановится именно в предопределенной точке от начала вашего сеанса отладки. 13.4.1.2. Что Вы должны сделать для заглушки Отладочные заглушки, поставляемые с GDB, ориентированы на микропроцессоры определенной архитектуры, но они не имеют информации об остальной части вашей целевой машины. Сперва вам нужно сообщить заглушке, как связаться с последовательным портом. `int getDebugChar()' Напишите эту подпрограмму для чтения одного символа из последовательного порта. Она может быть идентична `getchar' для вашей целевой системы; разные имена используются, чтобы позволить вам различать их, если вы хотите. `void putDebugChar(int)' Напишите эту подпрограмму для записи одного символа в последовательный порт. Она может быть идентична `putchar' для вашей целевой системы; разные имена используются, чтобы позволить вам различать их, если вы хотите. Если вы хотите, чтобы GDB мог остановить вашу программу во время выполнения, вам нужно использовать последовательный драйвер управления - 159 - прерываниями и организовать для него останов по получении `^C' (`\003', символ control-C). Этот символ GDB использует для указания удаленной системе остановиться. Указание отладочной цели вернуть соответствующий статус GDB, вероятно, требует изменений стандартной заглушки; один быстрый и грязный способ - только выполнить инструкцию точки останова ( "грязный", так как GDB выдает сигнал `SIGTRAP' вместо `SIGINT'). Другие процедуры, которые Вы должны обеспечить, - это: `void exceptionHandler (int EXCEPTION_NUMBER, void *EXCEPTION_ADDRESS)' Напишите эту функцию для установки EXCEPTION_ADDRESS в таблицы обработки исключительных ситуаций. Вам нужно сделать это, потому что у заглушки нет способов узнать, какая таблица обработки особых ситуаций в вашей целевой системе (например, процессорная таблица может быть в ПЗУ, содержащем входы, указывающие на таблицу в ОЗУ). EXCEPTION_NUMBER - номер ситуации, для которой определяется процедура обработки; его значение зависит от архитектуры (например, различные номера могут представлять деление на нуль, доступ с нарушением выравнивания и т.д.). Когда возникает особый случай, управление должно быть передано непосредственно по адресу EXCEPTION_ADDRESS, и процессорное состояние (стек, регистры и т.п.) должно остаться таким же, как во время возникновения особого случая. Так что, если вы хотите использовать инструкцию перехода к EXCEPTION_NUMBER, это должен быть простой переход, не переход к подпрограмме. Для 386 EXCEPTION_ADDRESS должен устанавливаться как обработчик прерывания, чтобы остальные прерывания маскировались, пока выполняется данный обработчик. Он должен иметь уровень привелегий 0 (наиболее привелегированный уровень). Заглушки SPARC и 68K могут маскировать прерывания самостоятельно без помощи `exceptionHandler'. `void flush_i_cache()' (только sparc и sparclite). Напишите эту попрограмму для заполнения кэша командн, если он есть, на вашей целевой машине. - 160 - Если кэша команд нет, эта подпрограмма может быть пустой операцией(no-op). На целевых машинах, имеющих кэш команд, GDB требуется эта функция, чтобы удостовериться, что состояние вашей программы стабильное. Вы должны также удостовериться, что доступна такая библиотечная процедура: `void *memset(void *, int, int)' Это стандартная библиотечная функция `memset', которая устанавливает область памяти в известное значение. Если вы имеете одну из трех версий `libc.a', `memset' можно найти там; иначе вы должны получить ее от изготовителей аппаратного обеспечения или написать свою собственную. Если вы не используете GNU транслятор Си, вам также может понадобиться другая стандартная библиотечная подпрограмма; она меняется от одной заглушки к другой, но в общем, эти заглушки, вероятно, используют любые общие библиотечные подпрограммы, которые `gcc' генерирует как встроенный код. 13.4.1.3. Помещение всего вместе В итоге, когда ваша программа готова к отладке, вы должны проделать следующие шаги: 1. Убедитесь, что вы имеете поддерживающие процедуры низкого уровня (см.Раздел 13.4.1.2 [Что вы должны сделать для заглушки]): `getDebugChar', `putDebugChar', `flush_i_cache',`memset', `exceptionHandler'. - 161 - 2. Вставьте следующие строки близко от начала(top) вашей программы: set_debug_traps(); breakpoint(); 3. Только для заглушки 680x0, вы должны предусмотреть переменную `exceptionHook'. Обычно вы только используете: void (*exceptionHook)() = 0; но если перед вызовом `set_debug_traps' вы установили ее для указания функции в вашей программе, эта функция вызовется при продолжении `GDB' после останова на ловушке (например, ошибка шины). Функция, обозначенная `exceptionHook', вызывается с одним параметром: типа `int', который является номером особого случая. 4. Откомпилируйте и скомпонуйте вместе: вашу программу, отладочную заглушку GDB для вашей целевой архитектуры и поддерживающие подпрограммы. 5. Убедитесь, что имеете последовательную связь между вашей целевой машиной и головной GDB, и идентифицируйте последовательный порт на головной машине. 6. Выгрузите вашу программу на целевую машину (или получите ее там любыми средствами, обеспечиваемыми изготовителем) и запустите ее. 7. Для запуска дистанционной отладки запустите GDB на головной машине и определите как исполняемый файл программу, которая выполняется на удаленной машине. Это укажет GDB, как найти идентификаторы вашей программы и содержание ее текста. Затем установите связь, используя команду `target remote'. Ее параметры определяют, как установить связь с целевой машиной-- через устройство, подключенное к последовательной линии прямого доступа или к порту TCP (обычно к терминальному серверу), который в свою очередь имеет последовательную линию к цели). Например, чтобы использовать последовательную линию, связанную с устройством - 162 - `/dev/ttyb', выполните: target remote /dev/ttyb Чтобы использовать TCP соединение, используйте параметр в форме `HOST:port'. Например, для соединения с портом 2828 на терминальном сервере `manyfarms': target remote manyfarms:2828 Теперь вы можете использовать обычные команды проверки и изменения данных и пошагового выполнения(step) и продолжения удаленной программы. Для возобновления выполнения удаленной программы и останова ее отладки используйте команду `detach'. Всякий раз, когда GDB ожидает удаленную программу, если вы наберете символ прерывания (часто ^C), GDB попытается остановить программу. Это может пройти успешно или нет, частично в зависимости от аппаратныхх средств и последовательных драйверов, которые использует удаленная система. Если вы снова наберете символ прерывания, GDB выведет сообщение: Interrupted while waiting for the program. Give up (and stop debugging it)? (y or n) Если вы наберете `y', GDB покинет сеанс дистанционной отладки. (Если вы решите, что хотите попытаться снова позже, вы можете использовать `target remote' снова для соединения еще раз.) Если вы наберете `n', GDB вернется к ожиданию. 13.4.1.4. Протокол связи Файлы заглушек, поставляемые с GDB, реализуют протокол связи со стороны целевой машины, а GDB-сторона реализуется исходным файлом GDB `remote.c'. Обычно вы просто используете эти программы для обеспечения - 163 - связи, игнорируя детали. (Если вы разрабатываете собственный файл заглушки, вы также можете игнорировать многие детали, используя в качестве прототипа один из существующих файлов заглушки. `sparc-stub.c' организован наилучшим образом и поэтому наиболее легок для чтения.) Однако, бывают случаи, когда вам необходимо что-нибудь знать о протоколе - например, если на вашей целевой машине только один последовательный порт и вы хотите, чтобы ваша программа делала что-нибудь особенное, если она распознает предназначенный для GDB пакет. Все команды и ответы GDB (не путать с односимвольными подтверждениями) посылаются как пакет, включающий контрольную сумму. Пакет начинается символом `$' и оканчивается символом `#', сопровождаемым контрольной суммой из двух цифр: $PACKET INFO#CHECKSUM CHECKSUM вычисляется как сумма по модулю 256 кодов литер пакета PACKET INFO. Когда головная или целевая машина получает пакет, первый ожидаемый ответ - подтверждение: один символ - или `+' (для указания, что пакет был получен корректно), или `-' (для запроса повторной передачи). Головная машина (GDB) посылает команды, а целевая (отладочная заглушка, включенная в вашу программу) посылает в ответ данные. Целевая машина также посылает данные при останове программы. Пакеты команд отличаются первым символом, который определяет тип команды. Вот некоторые из команд, поддерживаемых в настоящее время (полный список команд смотрите в файле `gdb/remote.c'): - 164 - `g' Запрашивает значения регистров ЦП. `G' Устанавливает значения регистров ЦП. `mADDR,COUNT' Читает COUNT байтов по адресу ADDR. `MADDR,COUNT:...' Записывает COUNT байтов по адресу ADDR. `c' `cADDR' Возобновляет выполнение по текущему адресу (или ADDR, если указано). `s' `sADDR' Осуществляет пошаговое выполнение целевой программы по одной команде, с текущего значения счетчика или с ADDR, если указано. `k' Уничтожает целевую программу. `?' Сообщает самый последний сигнал. Чтобы позволить вам пользоваться преимуществами команд обработки сигналов GDB, одной из функций отладочной заглушки является сообщение о ловушках ЦП соответствующими значениями сигнала POSIX. `T' Позволяет удаленной заглушке посылать только регистры, в которых GDB нуждается для осуществления быстрых решений относительно пошагового выполнения или условных точек останова. Это устраняет потребность выбирать весь набор регистров, для каждой выполняемой инструкции. - 165 - Удаленный последовательный протокол GDB теперь включает кэш сквозной записи для регистров. GDB заново считывает регистры, только если цель выполнилась. Если у вас возникли трудности с последовательным соединением, вы можете использовать команду `set remotedebug'. Она заставляет GDB сообщить обо всех пакетах, посланных туда и обратно через последовательную линию удаленной машине. Информация пакетной отладки печатается в стандартном потоке вывода GDB. `set remotedebug off' отключает ее, а `show remotedebug' показывает ее текущее состояние. 13.4.1.5. Использование программы `gdbserver' `gdbserver' является управляющей программой для Unix-подобных систем, которая позволит вам установить соединение вашей программы с удаленной GDB через `target remote', но без связывания в обычной отладочной заглушке. `gdbserver' не полная замена для отладочной заглушки, потому что требует по существу тех же средств операционной системы, как и сам GDB. Фактически, система, которая может запустить `gdbserver' для соединения с удаленной GDB, может также локально запустить GDB. `gdbserver' все-таки иногда полезна, так как по размеру она гораздо меньше, нежели непосредственно GDB. Ее также легче переносить, чем весь GDB, так что вы сможете быстрее запуститься в новой системе, используя `gdbserver'. Наконец, если вы разрабатываете программы для систем реального времени, вы знаете, что из-за сопряженных с операциями реального времени трудностями удобнее как можно большую часть разработки выполнять на другой системе, например, использую кросс-компиляцию. При помощи `gdbserver' вы осуществляете подобный выбор для этапа отладки. GDB и `gdbserver' сообщаются через последовательную линию или TCP соединение, используя стандартный удаленный последовательный протокол GDB. - 166 - *На целевой машине,* вам необходимо иметь копию программы, которую вы хотите отладить. `gdbserver' не нуждается в таблице символов вашей программы, так что вы можете сократить вашу программу, если необходимо сохранить пространство. GDB на головной машине проделывает всю обработку идентификаторов. Чтобы использовать сервер, вы должны сообщить ему как общаться с GDB; имя вашей программы; и параметры для вашей программы. Синтаксис следующий: target> gdbserver COMM PROGRAM [ ARGS ... ] COMM - имя устройства (для использования последовательной линии), или имя TCP на головной машине и номер порта. Например, для отладки Emacs с параметром `foo.txt' и сообщения с GDB через последовательный порт `/dev/com1': target> gdbserver /dev/com1 emacs foo.txt `gdbserver' пассивно ждет головного GDB для связи с ним. Чтобы использовать TCP соединение вместо последовательной линии: target> gdbserver host:2345 emacs foo.txt Единственная разница с предыдущим примером в первом параметре, определяющем, что вы связываетесь с головным GDB через TCP. Параметр `host:2345' означает, что `gdbserver' должен ожидать TCP соединения от машины `host' к локальному порту TCP 2345. (В настояшее время часть `host' игнорируется.) Вы можете выбрать любой номер порта, если при этом он не конфликтует с какими-либо портами TCP, уже использующимися целевой системой (например, `23' зарезервирован для `telnet'). Если вы выберете номер порта, конфликтующего с другим сервером, `gdbserver' печатает сообщение об ошибке и выходит. Вы должны использовать тот же номер порта с командой головного GDB `target remote'. - 167 - *На головной машине GDB,* вам нужна несокращенная копия вашей программы, так как GDB нужна идентификаторная и отладочная информация. Запустите GDB как обычно, используя имя локальной копии вашей программы в качестве первого параметра. (Вам также может понадобиться опция `--baud', если последовательная линия имеет скорость, отличную от 9600 бит/сек.) После этого используйте `target remote' для установки сообщения с `gdbserver'. Ее параметры - или имя устройства (обычно последовательного устройства, такого как `/dev/ttyb'), или дескриптор порта TCP в форме `HOST:PORT'. Например: (gdb) target remote /dev/ttyb сообщается с сервером через последовательную линию `/dev/ttyb' и (gdb) target remote the-target:2345 сообщается через TCP соединение с портом 2345 на головной машине `the-target'. Для TCP соединения вы должны запустить `gdbserver' до использования команды `target remote'. Иначе вы можете получить ошибку, текст которой зависит от головной системы, но обычно он выглядит примерно так: `Connection refused'. 13.4.1.6. Использование программы `gdbserve.nlm' `gdbserve.nlm' является управляющей программой для систем NetWare, которая позволяет вам установить соединение вашей программы с удаленным GDB через `target remote'. GDB и `gdbserve.nlm' сообщаются через последовательную линию, используя стандартный удаленный последовательный протокол GDB. *На целевой машине,* вам необходимо иметь копию программы, которую вы хотите отладить. `gdbserve.nlm' не нуждается в таблице символов вашей программы, так что вы можете сократить вашу программу, если необходимо сохранить пространство. GDB на головной машине проделывает всю - 168 - обработку идентификаторов. Чтобы использовать сервер, вы должны сообщить ему как общаться с GDB; имя вашей программы; и параметры для вашей программы. Синтаксис следующий: load gdbserve [ BOARD=BOARD ] [ PORT=PORT ] [ BAUD=BAUD ] PROGRAM [ ARGS ...] BOARD и PORT определяют последовательную линию; BAUD определяет скорость в бодах, используемую соединением. Значения PORT и NODE по умолчанию 0, BAUD по умолчанию 9600 бит/сек. Например, для отладки Emacs с параметром `foo.txt' и сообщающегося с GDB через последовательный порт номер 2 на плате 1, использующий соединение 19200 бит/сек.: load gdbserve BOARD=1 PORT=2 BAUD=19200 emacs foo.txt *На головной машине GDB,* вам нужна несокращенная копия вашей программы, так как GDB нужна идентификаторная и отладочная информация. Запустите GDB как обычно, используя имя локальной копии вашей программы в качестве первого параметра. (Вам также может понадобиться опция `--baud', если последовательная линия имеет скорость, отличную от 9600 бит/сек.) После этого используйте `target remote' для установки сообщения с `gdbserve.nlm'. Ее параметры - или имя устройства (обычно последовательного устроцства, такого как `/dev/ttyb'). Например: (gdb) target remote /dev/ttyb соединение с сервером через последовательную линию `/dev/ttyb'. - 169 - 13.4.2. GDB с удаленным i960 (Nindy) "Nindy" является программой монитора ROM для целевых систем Intel 960. Когда GDB сконфигурирован для управления удаленным Intel 960 с использованием Nindy, вы можете сообщить GDB, как сообщаться с 960 несколькими способами: * Через опции командной строки, определяющие последовательный порт, версию Nindy и скорость связи; * Отвечая на сообщение при запуске; * Используя команду `target' в любой точке во время вашего сеанса GDB. См.Раздел 13.2 [Команды управления целями]. 13.4.2.1. Запуск с Nindy Если вы просто запустите`gdb' без использования опций командной строки, вас спросят, какой используется последовательный порт, до того, как вы получите обычные сообщения GDB: Attach /dev/ttyNN -- specify NN, or "quit" to quit: Ответьте на сообщение с любым суффиксом (после `/dev/tty'), определяющим последовательный порт, который вы хотите использовать. По выбору, вы можете просто запуститься без Nindy соединения, если ответите на сообщение пустой строкой. Если вы сделали это и позже захотите присоединиться к Nindy, используйте `target' (см.Раздел 13.2 [Команды управления целями]). - 170 - 13.4.2.2. Опции для Nindy Это опции запуска для начала вашего сеанса GDB с подключенной платой Nindy-960: `-r PORT' Определяет имя последовательного порта последовательного интерфейса, который должен использоваться для соединения с целевой системой. Эта опция доступна, когда GDB сконфигурирован для целевой архитектыры Intel 960. Вы можете определить PORT, как любой из: полный путь (например, `-r/dev/ttya'), имя устройства в `/dev' (например, `-r ttya') или просто уникальный суффикс для спецификации `tty' (например, `-r a'). `-O' (Литера `O' верхнего регистра, не нуль.) Определяет, что GDB следует использовать "старый"("old") протокол монитора Nindy для соединения с целевой системой. Эта опция доступна, только когда GDB сконфигурирован для целевой архитектуры Intel 960. *Предупреждение:* если вы определили `-O', но в действительности пытаетесь связаться с системой, которая ожидать нового протокола, соединение откажет, появится несоответствие скоростей. GDB неоднократно попытается снова соединиться при нескольких различных скоростях линии. Этот процесс можно остановить посредством прерывания. `-brk' Определяет, что сперва GDB должен послать сигнал `BREAK' целевой системе, пытаясь сбросить ее перед соединением с целевым Nindy. *Предупреждение:* Многие целевые системы не имеют требуемых для этого аппаратных средств; это работает только на некоторых платах. Стандартная опция `-b' управляет скоростью линии, используемой в последовательном порту. - 171 - 13.4.2.3. Команда сброса Nindy `reset' Для целевых Nindy эта команда посылает "break" удаленной целевой системе; она полезна, только если целевая система оборудована схемой, представляющей аппаратный сброс (или другое интересующее действие) при обнаружении прерывания. 13.4.3. UDI-протокол для AMD29K GDB поддерживает UDI ("Universal Debugger Interface") протокол AMD для отладки семейства процессоров a29k. Чтобы использовать эту конфигурацию с целями AMD, запускающими монитор MiniMON, вам нужна программа `MONTIP', безвозмездно доступная из AMD. Вы также можете использовать GDB с программой UDI-совместимого имитатора a29k `ISSTIP', также доступной из AMD. `target udi KEYWORD' Выбирает интерфейс UDI для удаленной платы a29k или имитатора, где KEYWORD - вход в файл конфигурации AMD `udi_soc'. Этот файл содержит входы с ключевыми словами, которые определяют параметры, используемые для соединения с целями a29k. Если файл `udi_doc' находится не в вашем рабочем каталоге, вы должны установить значение системной переменной `UDICONF' в имя пути к нему. 13.4.4. EBMON-протокол для AMD29K AMD распространяет макетную плату 29K, вставляемую внутрь РС и используемую совместно с программой DOS-резидентного монитора`EBMON'. Сокращенно эта система макетирования называется "EB29K". Чтобы использовать GDB из системы Unix для выполнения программ на плате EB29K, вы должны сперва протянуть последовательный кабель между PC (который управляет платой EB29K) и последовательным портом системы Unix. Далее, предположим, что вы протянули кабель между портом PC `COM1' и `/dev/ttya' в системе Unix. - 172 - 13.4.4.1 Установка соединений Следующий шаг - установка порта PC, например, путем выполнения следующей команды DOS на PC. C:\> MODE com1:9600,n,8,1,none Этот пример, выполненный в системе MS DOS 4.0, устанавливает PC порт на скорость 9600 бит/сек., без контроля по четности, восемь информационных бит, с одним стоповым битом и без каких-либо повторов; вы также должны согласовывать параметры связи при установке Unix конца соединения. Чтобы передать контроль над PC Unix стороне последовательной линии, наберите на консоли DOS следующее: C:\> CTTY com1 (Позже, если вы захотите вернуть управление консоли DOS, вы можете использовать команду `CITY con'--но вы должны послать ее с устройства, имеющего управление, в нашем примере с последовательной линии `COM1'). Из головного Unix используйте программу связи типа `tip' или `cu' для связи с PC; например, cu -s 9600 -l /dev/ttya Показанные опции `cu' определяют, соответственно, используемые скорость линии и последовательный порт. Если вы вместо этого используете `tip', ваша командная строка может выглядеть примерно так: tip -9600 /dev/ttya Ваша система может требовать другое имя, где мы указали `/dev/ttya', в качестве параметра `tip'. Параметры связи, включая используемый порт, связаны с аргументом `tip' в "удаленном"("remote") файле - 173 - описаний--обычно системной таблице `/etc/remote'. Используя соединение `tip' или `cu', смените рабочий каталог DOS на каталог, содержащий копию вашей программы 29K, затем запустите программу PC `EBMON' (программа управления EB29K, поддерживаемая AMD на вашей плате). Вы должны просмотреть начальный дисплей(initial display) `EBMON', подобный одному из следующих, заканчивающихся сообщением `EBMON' `#'- C:\> G: G:\> CD \usr\joe\work29k G:\USR\JOE\WORK29K> EBMON Am29000 PC Coprocessor Board Monitor, version 3.0-18 Copyright 1990 Advanced Micro Devices, Inc. Written by Gibbons and Associates, Inc. Enter '?' or 'H' for help PC Coprocessor Type = EB29K I/O Base = 0x208 Memory Base = 0xd0000 Data Memory Size = 2048KB Available I-RAM Range = 0x8000 to 0x1fffff Available D-RAM Range = 0x80002000 to 0x801fffff PageSize = 0x400 Register Stack Size = 0x800 Memory Stack Size = 0x1800 CPU PRL = 0x3 Am29027 Available = No Byte Write Available = Yes # ~. - 174 - Затем выйдите из программы `cu' или `tip' (в примере это сделано набором `~.' в сообщении `EBMON'). `EBMON' продолжает выполняться, готовая принять GDB. Для этого примера мы приняли наиболее удобный способ удостовериться, что на PC и в системе Unix одна и та же программа 29K: PC/NFS соединение, которое устанавливает "диск `G:`" на PC, как файловую систему на головном Unix. Если у вас нет PC/NFS или чего-нибудь, соединяющего две системы подобным образом, вы должны организовать какой-нибудь другой путь - возможно, передачу гибкого диска - получения программы 29K из системы Unix на PC; GDB не выгружает ее по последовательной линии. 13.4.4.2. Кросс-отладка EB29K В заключении, переключитесь(`cd') на каталог, содержащий образ вашей программы 29K в системе, и запустите GDB--определяя в качестве аргумента имя вашей программы 29K: cd /usr/joe/work29k gdb myfoo Теперь Вы можете использовать команду `target': target amd-eb /dev/ttya 9600 MYFOO В этом примере предполагается, что ваша программа содержится в файле `myfoo'. Обратите внимание, что имя файла, заданное, как последний параметр `target amb-eb', должно быть именем программы, как оно указано в DOS. В нашем примере это просто `MYFOO', но в общем оно может включать в себя путь DOS и, в зависимости от вашего механизма передачи, может не соответствовать имени на Unix стороне. Теперь вы можете устанавливать любые точки останова, какие пожелаете; когда вы готовы увидеть свою программу выполняющейся на плате 29K, используйте команду `run'. - 175 - Для останова отладки удаленной программы используйте команду GDB `detach'. Для возвращения контроля над PC его консоли снова используйте `tip' или `cu' после завершения сеанса GDB для присоединения к `EBMON'. Вы можете набрать команду `q' для отключения `EBMON' с возвращением управления интерпретатору командной строки DOS. Наберите `CITY con' для возвращения ввода команд головной консоли DOS и `~.', чтобы покинуть `tip' или `cu'. 13.4.4.3. Отдаленный журнал Команда `target amb-eb' создает файл `eb.log' в текущем рабочем каталоге, чтобы помочь рещению отладочных проблем с соединением. `eb.log' записывает весь вывод `EBMON', включая эхо команд, посылаемых ей. Выполнение `tail -f' на этом файле в другом окне часто помогает понять затруднения с `EBMON' или неожиданные события на PC стороне соединения. 13.4.5. GDB с Tandem ST2000 Чтобы соединить ваш ST2000 c головной системой, см.руководство изготовителя. Если ST2000 физически присоединен, вы можете выполнить: target st2000 DEV SPEED для установки его в качестве отладочной среды. DEV - обычно имя последовательного устройства типа `/dev/ttya', соединенного с ST2000 через последовательную линию. Взамен вы можете определить DEV как TCP соединение (например, последовательную линию, подключенную через оконечный накопитель), используя синтаксис `HOSTNAME:PORTNUMDER'. Команды `load' и `attach' не определены для этой цели; вы должны загружать вашу программу в ST2000, как вы обычно делаете это для автономной работы. GDB читает отладочную информацию (такую как идентификаторы) из отдельных отладочных версий программы, доступных на - 176 - вашем головном компьютере. Эти вспомогательные команды GDB доступны для помощи вам в работе со средой ST2000: `st2000 COMMAND' Посылает команду COMMAND монитору STDBUG. См.доступные команды в руководстве изготовителя. `connect' Связывает управляющий терминал с командным монитором STDBUG. Когда вы осуществили взаимодействие с STDBUG, набор последовательности из двух символов вернет вас обратно в командную строку GDB: `RET~.' (Return, сопровождаемый тильдой и точкой) или `RET~C-d' (Return, сопровождаемый тильдой и control-d). 13.4.6. GDB и VxWorks GDB дает возможность разработчикам порождать и отлаживать задачи, выполняющиеся на сетевых VxWorks целях из Unix головных систем. Уже выполняющиеся задачи, порожденные оболочкой VxWorks, также могут быть отлажены. GDB использует код, выполняющийся и в головном Unix, и в целевых VxWorks. Программа `gdb' устанавливается и выполняется в головном Unix. (Она может быть установлена с именем `vxgdb' для отличия от GDB, отлаживающего программы на головной машине.) `VxWorks-timeout ARGS' Все базирующиеся на VxWorks цели в настоящее время поддерживают опцию `vxworks-timeout'. Эта опция устанавливается пользователем, и ARGS представляет собой количество секунд, в течении которых GDB ждет ответов на RPC-запросы. Вы можете использовать ее, если ваша целевая VxWorks - медленный программный имитатор или подключена к сети при помощи длинного тонкого кабеля. Излагаемая ниже информация относительно соединения с VxWorks была текущей на момент выпуска этого руководства; новейшие реализации - 177 - VxWorks могут использовать модифицированные процедуры. Для использования GDB с VxWorks вы должны перестроить ядро вашей VxWorks для включения в него процедур удаленного отладочного интерфейса из библиотеки VxWorks `rdb.a'. Для этого определите `INCLUDE_RDB' в файле конфигурации VxWorks `configAll.h' и перестройте ядро VxWorks. В результате ядро содержит `rdb.a' и порождает исходную отладочную задачу `tRdbTask' при загрузке VxWorks. Для получения большей информации по конфигурированию и перестраиванию VxWorks см.руководство изготовителя. Если вы включили `rdb.a' в ваш образ системы VxWorks и установили в вашем выполнении Unix путь поиска для нахождения GDB, вы готовы запустить GDB. Из вашего головного Unix запустите `gdb' (или `vxgdb', в зависимости от вашей установки). GDB запускается, высвечивая сообщеение: (vxgdb) 13.4.6.1. Соединение с VxWorks Команда GDB `target' позволит вам соединиться с целевой VxWorks по сети. Для соединения с целью с именем "`tt'",наберите: (vxgdb) target vxworks tt GDB отображает сообщения наподобие этих: Attaching remote machine across net... Connected to tt. Затем GDB попытается прочитать таблицы символов объектных модулей, загруженных в целевую VxWorks после последней перезагрузки. GDB определяет местоположение этих файлов, ища каталоги, перечисленные в командной строке поиска (см.Раздел 4.4 [Рабоча среда вашей программы]); если она не сможет найти объектный файл, она высветит - 178 - сообщение типа: prog.o: No such file or directory. Когда это произойдет, добавьте соответствующий каталог в путь поиска командой GDB `path' и снова выполните команду `target'. 13.4.6.2. Загрузка в VxWorks Если вы установили соединение с целевой VxWorks и хотите отладить объект, который еще не был загружен, вы можете использовать команду GDB `load' для выгрузки файла из Unix в VxWorks. Объектный файл, заданный как аргумент команды `load' в действительности открывается дважды: первый раз VxWorks при загрузке кода, затем GDB для прочтения таблицы символов. Это может привести к проблемам, если текущий рабочий каталог различен в двух системах. Если обе системы имеют NFS, который монтирует одинаковые файловые системы, вы можете избежать этих проблем, используя абсолютный путь. В противном случае проще всего установить рабочий каталог в обеих системах тот, в котором постоянно находится объектный файл и ссылаться на него по имени, без пути. Например, программа `prog.o' может постоянно находиться в VxWorks в `VXPATH/vm/demo/rdb', а на головной машине в `HOSTPATH/vm/demo/rdb'. Для загрузки этой программы наберите в VxWorks следующее: -> cd "VXPATH/vw/demo/rdb" Затем наберите в GDB: (vxgdb) cd HOSTPATH/vw/demo/rdb (vxgdb) load prog.o GDB отображает ответ, подобный этому: Reading symbol data from wherever/vw/demo/rdb/prog.o... done. Также вы можете использовать команду `load' для перезагрузки объектного модуля после редактирования и перекомпиляции - 179 - соответствующего исходного файла. Обратите внимание, что это заставит GDB удалить все определенные в данный момент точки останова, автоотображения и рабочие переменные и очистить архив значений. (Это необходимо, чтобы сохранить целостность отладочных структур данных, которые ссылаются на таблицу символов целевой системы.) 13.4.6.3. Выполняющиеся задачи Вы также можете подключиться к существующей задаче, используя команду `attach' следующим образом: (vxgdb) attach TASK где TASK - шестнадцатиричная задача ID VxWorks. Задача может выполняться или быть приостановленной, когда вы подключаетесь к ней. Выполняющаяся задача приостанавливается в момент подключения. 13.4.7. GDB и микропроцессоры Hitachi GDB должен знать следующее для общения с вашим Hinachi SH, H8/300 или H8/500: 1. что вы хотите использовать, `target hms', удаленный отладочный интерфейс для микропроцессоров Hitachi, или `target e7000', внутрисхемный эмулятор для Hitachi SH и Hitachi 300H (`target hms' установлено по умолчанию, когда GDB сконфигурирован специально для Hitachi SH, H8/300 или H8/500). 2. какое последовательное устройство соединяет вашу головную машину с платой Hitachi ( по умолчанию, первое устройство, доступное на вашей головной машине). 3. какую скорость использовать в последовательном устройстве. - 180 - 13.4.7.1 Соединение с платами Hitachi Используйте специальную команду `gdb' `device PORT', если вам нужно явно установить последовательное устройство. По умолчанию PORT - первый доступный порт на вашей головной машине. Это необходимо только на головных Unix и обычно выглядить похоже на `/dev/ttya'. GDB имеет еще одну специальную команду для установки скорости связи: `speed BPS'. Эта команда также используется только для головных Unix-систем; на головных DOS-системах устанавливайте скорость линии как обычно с внешнего GDB командой DOS `mode' (например, `mode com-:9600,n,8,1,p' для связи 9600 бит/сек.). Команды `device' и `speed' доступны, только когда вы используете головную Unix для отладки программ вашего микропроцессора Hitachi. Если вы используете головную DOS-машину, GDB зависит от вспомогательной резидентной программы `asynctsr' для сообщения с макетной платой через последовательный порт PC. Вы должны также использовать команду DOS `mode' для установки последовательного порта на DOS стороне. 13.4.7.2. Использование внутрисхемного эмулятора E7000 Вы можете использовать внутрисхемный эмулятор E7000 для разработки кода для Hitachi SH или H8/300H. Используйте одну из этих форм команды `target e7000' для присоединения GDB к вашему E7000: `target e7000 PORT SPEED' Используйте эту форму, если ваш E7000 подключен к последовательному порту. Параметр PORT определяет, какой последовательный порт используется (например, `com2'). Третий аргумент - скорость линии в битах в секунду (например, `9600'). `target e7000 HOSTNAME' Если ваш E7000 установлен как головная машина в сети TCP/IP, вы можете только определить только имя головной машины; GDB использует для соединения `telnet'. - 181 - 13.4.7.3. Специальные команды GDB для микросхем Hitachi Некоторые команды GDB доступны только на конфигурациях H8/300 или H8/500: `set machine h8300' `set machine h8300h' Создает GDB для одного из двух вариантов архитектуры H8/300 посредством `set machine'. Вы можете использовать `show machine' для проверки, какой вариант действителен в данный момент. `set memory MOD' `show memory' Определите посредством `set memory', какую модель памяти (MOD) H8/500 вы используете; проверьте посредством `show memory', какая модель памяти действительна. Принимаемые значения для MOD - `small', `big', `medium' и `compact'. 13.4.8. GDB и удаленныe платы MIPS GDB может использовать удаленный MIPS протокол отладки для сообщения с MIPS платой, подключенной к последовательной линии. Это доступно, когда Вы сконфигурировали GDB с " - target=mips-idt-ecoff ". Используйте следующие команды GDB для определения связи с вашей целевой платой: `target mips PORT' Чтобы выполнять программу на плате, запустите 'gdb' с именем вашей программы в качестве параметра. Для связи с платой используйте команду `target mips PORT', где PORT - имя последовательного порта, связанного с платой. Если программа еще не выгружена на плату, вы можете использовать команду `load', чтобы выгрузить ее. Затем вы можете использовать все обычные команды GDB. - 182 - Например, следующая последовательность команд осуществляет связь с целевой платой через последовательный порт и загружает и выполняет программу PROG через отладчик: host$ gdb PROG GDB is free software and ... (gdb) target mips /dev/ttyb (gdb) load PROG (gdb) run `target mips HOSTNAME:PORTNUMBER' В некоторых основных конфигурациях GDB, Вы можете назначить TCP соединение (например, к последовательной линии, управляемой оконечным концентратором) вместо последовательного порта, используя синтаксис " HOSTNAME:PORTNUMBER ". GDB также поддерживает следущие специальные команды для целевых MIPS: `set processor ARGS' `show processor' Используйте команду `set processor' для установки типа MIPS-процессора, когда Вы хотите получить доступ к регистрам, зависящим от типа процессора. Например, `set processor R3041' сообщает GDB, что нужно использовать регистры CPO, соответствующие 3041 чипу. Используйте команду `show processor', чтобы увидеть, какой MIPS процессор используется GDB. Используйте команду `info reg', чтобы увидеть, какие регистры GDB используются. `set mipsfpu double' `set mipsfpu single' `set mipsfpu none' `show mipsfpu' Если ваша целевая плата не поддерживает MIPS сопроцессор с плавающей точкой, вы должны использовать команду `set mipsfpu none' (если вам нужно, вы можете поместить ее в ваш `.gdbinit' файл). Она сообщает GDB, как найти возвращаемое значение функций, - 183 - которые возвращают значения с плавающей точкой. Она также позволяет GDB избежать сохранения регистров с плавающей точкой при вызове функций на плату. Если вы используете сопроцессор с плавающей точкой, поддерживающий только одинарную точность, как в R4650 процессоре, используйте команду `set mipsfpu single'. Устанавливаемая по умолчанию двойная точность сопроцессора с плавающей точкой может быть выбрана с помощью `set mipsfpu double'. В предыдущих версиях единствеными вариантами были двойная точность или точность без точки, так что `set mipsfpu on' выберет двойную точность, а `set mipsfpu off' выберет точность без точки. Как обычно, вы можете запрашивать значение переменной 'mipsfpu' с помощью `show mipsfpu'. `set remotedebug N' `show remotedebug' Вы можете увидеть некоторую отладочную информацию относительно связи с платой установкой переменной 'remotedebug'. Если Вы устанавливаете ее в '1', используя `set remotedebug 1', отображается каждый пакет. Если Вы устанавливаете ее в '2', отображается каждый символ. Вы можете проверять ее текущее значение в любое время командой `show remotedebug'. `set timeout SECONDS' `set retransmit-timeout SECONDS' `show timeout' `show retransmit-timeout' Вы можете управлять временем ожидания события, используемым при ожидании пакета, в удаленном протоколе MIPS, с помощью команды `set timeout SECONDS'. Значение по умолчанию - 5 секунд. Аналогично Вы можете управлять временем ожидания события, используемым при ожидании подтверждения приема пакета с помощью команды `set retransmit-timeout SECONDS'. Значение по умолчанию - 3 секунды. Вы можете проверить оба значения командами `show timeout' и `show retransmit-timeout'. (Эти команды доступны, *только* когда GDB сконфигурирован для " - target=mips-idt-ecoff - 184 - ".) Установка времени ожидания события посредством `set timeout' не применяется, когда GDB ждет остановки вашей программы. В этом случае GDB ждет вечно, потому что невозможно узнать, как долго программа будет выполняться до остановки. 13.4.9. Целевой имитируемый ЦП Для некоторых конфигураций GDB включает имитатор центрального процессора, который Вы можете использовать вместо встроенного процессора для отладки ваших программ. В настоящее время имитатор доступен, когда GDB сконфигурирован для отладки целей Zilog Z8000 или микропроцессора Hitachi. Для семейства Z8000, `target sim' моделирует или Z8002 (несегментированный вариант архитектуры Z8000), или Z8001 (сегментированный вариант). Имитатор распознает, какая архитектура является соответствующей, проверяя объектный код. `target sim' Отлаживает программы с использованием моделируемого процессора (моделируемый процессор определяется конфигурацей GDB). После определения этой цели Вы можете отлаживать программы для моделируемого процессора в том же стиле, что и программы для вашего головного компьютера; используйте команду `file' для загрузки новой программы, команду `run' для выполнения вашей программы, и т.д. Кроме установки доступными всех обычных машинных регистров (см.`info reg'), этот тип отладочных целей обеспечивает три дополнительных элемента информации в виде трех специально именованных регистров: `cycles' Отсчеты часов в имитаторе. - 185 - `insts' Инструкции отсчетов выполняются в имитаторе. `time' Время выполнения в 60-ю долю секунды. Вы можете обратиться к их значениям в выражениях GDB с обычными соглашениями; например, `b fputc if $cycles>5000' устанавливает условную точку останова, остановка на которой происходит только после по крайней мере 5000 моделируемых отсчетов часов. 14. Управление GDB Вы можете изменять способы взаимодействия GDB с Вами, используя команду `set'. Для команд управления способами отображения данных, см.Раздел 8.7 [Установки вывода]; другие установки описаны здесь. 14.1. Приглашение GDB показывает свою готовность читать команду, выводя строку, называемую "приглашением". Обычно это - `(gdb)'. Вы можете изменить строку приглашения командой `set prompt'. Например, при отладке GDB с GDB, полезно изменить приглашение в одном из GDB сеансов так, чтобы Вы могли всегда понять, с чем Вы общаетесь. * Замечание: * `set prompt' не добавляет пробелы после установленного вами приглашения. Это позволяет устанавливать строку сообщений, которая заканчивается на пробел или нет. `set prompt NEWPROMPT' Указывает GDB, что далее надо использовать NEWPROMPT в качестве стpоки приглашения. `show prompt' Печатает строку в форме: `Gdb's prompt is: YOUR-PROMPT' - 186 - 14.2. Редактирование команд GDB читает входные команды через средства ввода строки (интерфейс "readline"). Эта библиотека GNU обеспечивает согласованный режим для программ, использующих пользовательский интерфейс типа командной строки. Преимущества: GNU Emacs-стиль или "vi"-стиль встроенного редактирования команд, 'csh'-подобная замена архива, и сохранение и вызов из архива команд во время сеансов отладки. Вы можете управлять режимом редактирования командной строки в GDB командой `set'. `set editing' `set editing on' Разрешение редактирования командной строки (разрешено по умолчанию). `set editing off' Запрещение редактирования командной строки. `show editing' Показывает, допускается ли редактирование командной строки. 14.3. Архив команд GDB может следить за командами, которые Вы вводите во время сеансов отладки, так, чтобы Вы могли точно знать, что происходило. Используйте следующие команды для управления объектами архива команд GDB. `set history filename FNAME' Установка имени файла архива команд GDB в FNAME. Это - файл, откуда GDB читает исходный список архива команд и куда он записывает архив команд этого сеанса, когда выходит из него. Вы можете обращаться к этому списку через расширение архива или с помощью редактирования архива команд. Этот файл по умолчанию есть значение переменной окружения `GDBHISTFILE', или - 187 - './.gdb_history', если эта переменная не определена. `set history save' `set history save on' Запись архива команд в файл, имя которого может быть определено командой `set history filename'. По умолчанию отключена. `set history save off' Не записывать архив команд в файл. `set history size SIZE' Установка числа команд, которые GDB хранит в архивном списке. По умолчанию это значение переменной окружения `HISTSIZE' или 256, если эта переменная не определена. Расширение архива предписывает специальное значение литере '!'. Так как '!' является также оператором "логического НЕ" в C, расширение архива отключено по умолчанию. Если Вы решите допустить расширение архива командой `set history expansion on', Вы должны будете снабдить '!' (когда он используется как "логическое не" в выражении) пробелом или меткой табуляции, чтобы предотвратить расширение архива. Средства "readline" не делают попытку подстановки на строках '!=' и '!(', даже когда расширение архива разрешено. Команды управления расширением архива: `set history expansion on' `set history expansion' Разрешение расширения архива. Расширение архива отключено по умолчанию. `set history expansion off' Запрещение расширения архива. Библиотека Readline поставляется вместе с более полной документацией по возможностям редактирования и расширения архива. Пользователи, незнакомые с GNU Emacs или 'vi', могут изучить ее. - 188 - `show history' `show history filename' `show history save' `show history size' `show history expansion' Эти команды отображают состояние параметров архива GDB. `show history' показывает состояние всех четырех параметров. `show commands' Отображает последние десять команд в архиве команд. `show commands N' Выводит десять команд, расположенных около команды с номером N. `show commands +' Выводит десять команд, следовавших сразу после последних выведенных команд. 14.4. Размеp экpана Некоторые команды GDB могут выводить большие количества информации на экран. Чтобы помочь вам читать ее, GDB приостанавливает вывод и запрашивает ввод в конце каждой страницы вывода. Нажмите RET, когда Вы хотите продолжить вывод, или 'q', если хотите завершить его. Установка ширины экрана определяет, когда пеpеносить стpоки вывода. В зависимости от того, что печатается, GDB пробует разбивать стpоку в удобочитаемом месте вместо того, чтобы просто разрешить пеpенос пpи заполнении стpоки. Обычно GDB узнает размер экрана из базы данных "termcap" по значению системной переменной `TERM' и установок 'stty rows' и 'stty cols'. При необходимости Вы можете изменить их командами `set height' и `set width': - 189 - `set height LPP' `show height' `set width CPL' `show width' Эти команды `set' определяют высоту экрана в LPP линий и ширину экрана в CPL символов. Соответствующие команды `show' отображают текущие установки. Если Вы определите высоту в нуль линий, GDB не приостанавливается во вpемя вывода, независимо от его размера. Это полезно, если вывод осуществляется в файл или буфер редактора. Аналогично, Вы можете определить `set width 0' для пpедотвpащения пеpеноса. 14.5. Числа Вы всегда можете вводить числа в восьмеричной, десятичной, или шестнадцатеричной системе в соответствии c обычными соглашениями: восьмеричные числа начинаются с `0', десятичные числа оканчиваются на `.' и шестнадцатеричные числа начинаются с `0x'. Числа, которые не начинаются ни c одного из этих знаков, по умолчанию считаются десятичными; аналогично, вывод по умолчанию для чисел, если не определен никакой специфический формат, осуществляется по основанию 10. Вы можете изменять основание, устанавливаемое по умолчанию для ввода и вывода командой `set radix'. `set input-radix BASE' Установка основания по умолчанию для числового ввода. Поддеpживаемые ваpианты для BASE 8, 10, или 16. BASE сама должна быть определена или недвусмысленно, или с использованием текущего основания системы счисления по умолчанию; например, любая из команд set radix 012 set radix 10. set radix 0xa - 190 - устанавливает десятичное основание. С другой стороны, `set radix 10' оставляет основание системы счисления неизменным независимо от того, каким оно было. `set output-radix BASE' Установка основания по умолчанию для числового вывода. Поддеpживаемые ваpианты для BASE 8, 10, или 16. BASE сама должна быть определена или недвусмысленно, или с использованием текущего основания системы счисления по умолчанию. `show input-radix' Отображает текущее основание по умолчанию для числового ввода. `show output-radix' Отображает текущее основание по умолчанию для числового вывода. 14.6. Необязательные предупреждения и сообщения По умолчанию GDB ничего не сообщает о своей собственной деятельности. Если Вы pаботаете на медленной машине, то можете при помощи команды `set verbose' заставить GDB выдавать Вам предупреждения в ситуациях, когда он выполняет большую внутреннюю работу, чтобы Вы не думали, что машина зависла. В этой версии команда `set verbose' управляет только сообщениями о загрузке таблиц символов исходного файла; см.`symbol-file' в Разделе 12.1 [Команды для определения файлов]. `set verbose on' Разрешает вывод опpеделенных информационных сообщений. `set verbose off' Отключает вывод опpеделенных информационных сообщений. `show verbose' Сообщает, как устанавлена `set verbose'. - 191 - По умолчанию, если GDB сталкивается с ошибками в таблице символов объектного файла, он не сообщает об этом; но если Вы отлаживаете компилятор, Вам может пригодиться эта информация (см.Раздел 12.2 [Ошибки чтения символьных файлов]). `set complaints LIMIT' Разрешает GDB выводить LIMIT сообщений о каждом типе необычных символов прежде, чем пеpестать сообщать о проблемах. Можете установить LIMIT в нуль для подавления всех сообщений или очень большим для предотвращения подавления сообщений. `show complaints' Выводит ограничение на вывод сообщений GDB о символах. По умолчанию GDB из осторожности задает, как иногда кажется, множество глупых вопросов, чтобы подтвердить некоторые команды. Например, если Вы пытаетесь выполнить программу, которая уже выполняется: (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) Если Вы желаете сами pазбиpаться с последствиями ваших собственных команд, Вы можете отключить эти запросы: `set confirm off' Отключает запросы подтверждения. `set confirm on' Допускает запросы подтверждения (по умолчанию). `show confirm' Показывает, выводится ли запросы подтверждения. - 192 - 15. Фиксированные последовательности команд Кроме команд точки останова (см.Раздел 5.1.7 [Списки команд точек останова]), GDB обеспечивает два способа сохранения последовательностей команд для выполнения целиком: команды, определяемые пользователем, и командные файлы. 15.1. Команды, определяемые пользователем "Команда, определяемая пользователем" - последовательность команд GDB, которой Вы назначаете имя, как новой команде. Имя назначается командой `define'. Команды пользователя могут иметь до 10 параметров, pазделенных пpобелами. Внутри определения команды пользователя параметры обозначаются как $ARG0 ...$ARG9. Тривиальный пример: define adder print $arg0 + $arg1 + $arg2 Для выполнения команды используется: adder 1 2 3 Этот пример определяет команду `adder', которая печатает сумму трех своих параметров. Обратите внимание, что параметры - текстовые подстановки, так что они могут ссылаться на переменные, использовать сложные выражения или даже выполнять вызовы низкоуpовневых функций . `define COMMANDNAME' Определяет команду COMMANDNAME. Если уже имеется команда с тем же именем, запрашивается подтверждение на ее переопределение. Определение команды делается из других командных строк GDB, которые задаются после команды `define'. Конец этих команд отмечается стpокой, содержащей `end'. - 193 - `if' Имеет один параметр - вычисляемое выражение. Команда сопровождается последовательностью команд, которые выполняются, если выражение истинно (отлично от нуля). Затем может следовать стpока `else', сопровождаемая последовательностью команд, которые выполняются при нулевом значении данного выражения. Конец списка отмечается стpокой, содержащей `end'. `while' Синтаксис подобен `if': команда имеет один параметр, который является вычисляемым выражением и сопровождается списком команд, по одной на стpоке, выполнение котоpого повторяется, пока выражение истинно. Конец списка отмечается стpокой `end'. `document COMMANDNAME' Описывает определенную пользователем команду COMMANDNAME так, чтобы к ней можно было обращаться посpедством `help'. Команда COMMANDNAME должна быть определена ранее. Команда `document' читает стpоки вводимой документации, точно также, как `define' читает стpоки определения команды, до строки 'end'. После завеpшения команды `document', введенная Вами документация будет отображаться командой `help' для команды COMMANDNAME. Вы можете использовать команду `document' неоднократно, чтобы изменять документацию команды. Переопределение команды посредством 'define' не изменяет документации. `help user-defined' Перечисляет все определенные пользователем команды вместе с первой строкой ее документации. `show user' `show user COMMANDNAME' Отображает определение команды COMMANDNAME (но не ее документацию). Если параметр COMMANDNAME не задан, выводятся определения всех определенных пользователем команд. - 194 - При выполнении определенной пользователем команды, внутренние команды определения не выводятся. Ошибка в любой из них останавливает выполнение всей определенной пользователем команды. В интерактивном режиме, команды, обычно запрашивающие подтверждение, выполняются без запроса, если они используется внутри определенной пользователем команды. Многие команды GDB, которые обычно выводят сообщения о том, что они делают, опускают сообщения, если используются в определенной пользователем команде. 15.2. Определяемые пользователем команды-ловушки Вы можете определять *ловушки* (hook), которые являются специальным видом определяемых пользователем команд. Всякий раз, при выполнении команды `foo', определенная пользователем команда `hook-foo' (если она существует) выполняется (без параметров) перед командой `foo'. Кроме того, существует псевдокоманда `stop'. Определение `hook-stop' заставляет выполняться связанные с ней команды при каждом останове вашей программы (т.е., при выполнении псевдокоманды `stop'): перед исполнением команд точек останова и выводом на экран сообщений или процедурных секций. Например, чтобы игнорировать сигналы `SIGALRM' во время выполнения в пошаговом режиме, но обрабатывать их при нормальном выполнении, Вы можете определить: define hook-stop handle SIGALRM nopass end define hook-run handle SIGALRM pass end define hook-continue handle SIGLARM pass - 195 - end Можно определить ловушку для любой однословной команды GDB, но не для псевдонимов команды: следует использовать базовое имя команды, например, `backtrace', а не 'bt'. Если во время выполнения вашей ловушки произойдет ошибка, выполнение команд GDB останавливается, и GDB выдаст приглашение (фактически введенная Вами команда не выполнится). Если Вы попытаетесь определить ловушку, не соответствующую никакой известной команде, Вы получите предупреждение от команды `define'. 15.3. Командные файлы Командный файл для GDB - файл, состоящий из строк с командами GDB. Такие файлы могут также включать комментарии (строки, начинающиеся с литеры '*'). Пустая строка в командном файле не выполняет ничего, а не означает повторение последней команды, как было бы при вводе команд с терминала. Когда Вы запускаете GDB, автоматически выполняются команды из его файлов инициализации (файлы '.gdbinit'). Сначала GDB читает файл инициализации (если он существует) в вашем домашнем каталоге, затем обрабатывает опции командной строки и операнды, после чего читает файл инициализации (если он существует) в текущем рабочем каталоге. Таким образом файл инициализации в вашем домашнем каталоге может устанавливать опции (такие, как `set complaints'), которые влияют на обработку опций и операндов командной строки. Файлы инициализации не выполняются, если Вы используете опцию `-nx'; cм.Раздел 2.1.2 [Выбор режима]. В некоторых конфигурациях GDB файлу инициализации приписывается иное имя (обычно это среды, где специализированная форма GDB должна сосуществовать с другими формами, следовательно должно быть отличное имя для файла инициализации специализированной версии). Следующие среды используют специальные имена файлов инициализации: - 196 - * VxWorks (Wind River Systems real-time OS): `.vxgdbinit' * OS68K (Enea Data Systems real-time OS): `.os68gdbinit' * ES-1800 (Ericsson Telecom AB M68000 emulator): `.esgdbinit' Вы можете также выполнить командный файл командой `source': `source FILENAME' Выполнить командный файл FILENAME. Строки в командном файле выполняются последовательно, при этом они не выводятся. Ошибка в любой команде приводит к завершению выполнения всего командного файла. Команды, запрашивающие подтверждение в интерактивном режиме, при использовании в командном файле выполняются без запросов. Многие команды GDB, обычно выводящие сообщения о том, что они делают, при вызове из командных файлов опускают эти сообщения. 15.4. Команды управления выводом При выполнении командного файла или определенной пользователем команды нормальный вывод GDB подавляется; единственый появляющийся вывод - тот, что явно выводится командами из определения. В этом разделе описываются три команды, используемые для получения того вывода, который вы хотите. `echo TEXT' Печатает TEXT. Непечатные литеры могут быть включены в TEXT при использовании управляющих последовательностей C, типа '\n' для перехода на новую строку. *Переход на новую строку не осуществляется без его определения.* В дополнение к стандартным управляющим последовательностям C, обратная косая черта, за которым следует пробел, замещает пробел. Это полезно для отображения строки с пробелами в начале или конце, поскольку ведущие и конечные пробелы урезаются из всех параметров. Чтобы - 197 - напечатать ` and foo = ', используйте команду `echo \ and foo =\'. Обратная косая черта в конце TEXT может использоваться, как и в C, для продолжения команды на следующие строки. Например, echo This is some text\n\ which is continued\n\ onto several lines.\n производит такой же вывод как echo This is some text\n echo which is continued\n echo onto several lines.\n `output EXPRESSION' Выводит значение EXPRESSION и ничего кроме него: никаких новых строк, никаких '$NN ='. Также значение не записываются в архив значений. См.Раздел 8.1 [Выражения]. `output/FMT EXPRESSION' Выводит значение EXPRESSION в формате FMT. Вы можете использовать такие же форматы, как для `print'. См.Раздел 8.4 [Форматы вывода] для получения большей информации. `printf STRING, EXPRESSIONS...' Выводит значение EXPRESSIONS, STRING задает формат. EXPRESSIONS отделены запятыми и могут быть числами или указателями. Их значения выводятся, точно так, как если бы ваша программа выполняла подпрограмму Cи printf (STRING, EXPRESSIONS...); Например, Вы можете напечатать два шестнадцатеричных значения: printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo - 198 - Единственые управляющие последовательности с обратной косой чертой, которые Вы можете использовать в строке формата - простые последовательности, состоящие из обратной косой черты, сопровождаемой литерой. 16. Использование GDB под управлением GNU Emacs Специальный интерфейс позволяет использовать GNU Emacs для просмотра (и редактирования) исходных файлов программы, которую Вы отлаживаете GDB. Чтобы использовать этот интерфейс, используйте команду 'M-x gdb' в Emacs. Задайте исполняемый файл, который Вы хотите отладить, в качестве параметра. Эта команда запускает GDB как подпроцесс Emacs с вводом и выводом через заново созданный буфер Emacs. Использование GDB под управлением Emacs такое же, как нормальное использование GDB, за исключением двух пунктов: * Весь "терминальный" ввод и вывод происходит через буфер Emacs. Это относится и к командам GDB и их выводу, и к вводу и выводу, которые производятся программой, которую Вы отлаживаете. Это полезно, т.к. Вы можете копировать текст предыдущих команд и вводить их снова; Вы даже можете таким же образом использовать части вывода. Все средства режима оболочки Emacs доступны для взаимодействия с вашей программой. В частности Вы можете посылать сигналы обычным путем - например, 'C-c C-c' для прерывания, 'C-c C-z' для останова. * GDB отображает исходный код через Emacs. Каждый раз, когда GDB отображает процедурную секцию, Emacs автоматически находит исходный файл для этой секции и помещает стрелку (`= >') на левом крае текущей строки. Emacs использует раздельный - 199 - буфер вывода и разделяет экран, чтобы отображать и сеанс GDB, и источник. Явная команда GDB `list' или команды поиска производят вывод как обычно, но у вас, вероятно, не будет причин использовать их под Emacs. *Предупреждение:* Если каталог, где находится ваша программа - не текущий, Emacs может неправильно определить местонахождение исходных файлов, если вспомогательный буфер отображений не показывает источник. GDB может находить программы, используя переменную окружения `PATH', тогда сеансы ввода и вывода происходят нормально; но Emacs не получает достаточно информации от GDB, чтобы разместить исходные файлы. Во избежание этой проблемы необходимо или запускать GDB из каталога, где находится ваша программа, или в качестве параметра `M-x gdb' использовать полное имя файла. Подобная путаница может возникнуть, если Вы используете команду GDB `file', чтобы переключиться на отладку программы, находящейся в другом месте. По умолчанию, `M-x gdb' вызывает программу `gdb'. Если вам нужно вызвать GDB под другим именем (например, если Вы храните несколько конфигураций под различными именами), Вы можете установить переменную Emacs 'gdb-command-name'; например, установка (setq gdb-command-name "mygdb") (предшествуемая `ESC ESC' или вводимая в `*рабочий*' буфер или в ваш `.emacs' файл) заставит Emacs вызвать программу "`mygdb'". В буфере ввода-вывода GDB Вы можете использовать следующие специальные команды Emacs в дополнение к стандартным командам оболочки: `C-h m' Описывает особенности режима GDB под Emacs. - 200 - `M-s' Выполнить до другой строки исходного текста, подобно команде GDB `step'; также обновить окна дисплея для показа текущего файла и его местонахождения. `M-n' Выполнить до следующей строки исходного текста в функции, пропуская все обращения к функциям, подобно команде GDB `next'. Затем обновить окно дисплея, чтобы показать текущий файл и его местонахождение. `M-i' Выполнить одну инструкцию, подобно команде GDB `stepi'; обновить окно дисплея. `M-x gdb-nexti' Выполнить до следующей инструкции, используя команду GDB 'nexti'; обновляет окно дисплея соответственно. `C-c C-f' Выполнить до выхода из выбранной процедурной секции, подобно команде GDB `finish'. `M-c' Продолжить выполнение программы, подобно команде GDB `continue'. *Предупреждение:* В Emacs v19, эта команда - `C-c C-p'. `M-u' Поднятся вверх по стеку на число процедурных секций, обозначенное числовым параметром, подобно команде GDB `up' (см.Раздел "Числовые Параметры" в "Описании GNU Emacs"). *Предупреждение:* В Emacs v19, эта команда - `C-c C-u'. `M-d' Спуститься вниз по стеку на число процедурных секций, обозначенное числовым параметром, подобно команде GDB `down'. - 201 - *Предупреждение:* В Emacs v19, эта команда - `C-c C-d'. `C-x &' Прочитать число в позиции курсора и вставить его в конец буфера ввода-вывода GDB. Например, если Вы желаете дисассемблировать код по адресу, отображенному ранее, наберите `disassemble'; затем переместите курсор на отображение адреса и выберите параметр для `disassemble', набирая `C-x &'. В дальнейшем Вы можете использовать настройки для `C-x &', определяя элементы списка `gdb-print-command'; если он определен, Вы можете форматировать или иначе обрабатывать числа, задаваемые `C-x &', перед их вставкой в буфер. Числовой параметр `C-x &' показывает, что конкретно Вы желаете форматировать, а также действует как индекс для выбора элемента списка. Если элемент списка - строка, то число, которое будет вставлено, форматируется с использованием функции Emacs `format'; иначе число передается как параметр к соответствующему элементу списка. В любом исходном файле команда Emacs `C-x SPC'(`gdb-break') указывает GDB установить точку останова на отметке строки исходного текста. Если Вы случайно удалили буфер исходного дисплея, его можно легко вернуть обратно - введите команду `f' в буфере GDB, чтобы запросить секцию отображения; когда выполнение происходит под управлением Emacs, исходный буфер создается вновь в том случае, если необходимо показать состояние текущей секции. Исходные файлы, отображаемые в Emacs, находятся в обычных буферах Emacs, который имеет доступ к исходным файлам обычным способом. При желании Вы можете редактировать файлы в этих буферах; но имейте в виду, что GDB связывается с Emacs посредством номеров строк. Если Вы добавляете или удаляете строки из текста, известные GDB номера строк больше не соответствуют коду. - 202 - 17. Сообщения о дефектах GDB Ваши сообщения о дефектах играют существенную роль в обеспечении надежности GDB. Сообщения о дефектах могут помочь Вам решить ваши проблемы, а могут и нет. Но в любом случае основная функция сообщения о дефектах - помочь разработчикам сделать следующую версию GDB лучше. Сообщения о дефектах - ваш вклад в разработку GDB. Чтобы можно было устранить причину дефекта, используя сообщение о дефектах, Вы должны включить в него информацию, которая даст нам возможность установить дефект. 17.1. Дефект ли Вы нашли? Для того чтобы определить, дефект ли Вы нашли, есть несколько руководящих принципов: * Если отладчик получает фатальный сигнал при любом вводе, что бы это ни было, - это дефект GDB. Надежные отладчики никогда не рушатся. * Если GDB выводит сообщение об ошибках для допустимого ввода, - это дефект. * Если GDB не выводит сообщение об ошибках для недопустимого ввода, - это дефект. Однако, Вы должны обратить внимание, что то, что по вашему мнению является "недопустимым вводом", может быть по нашему мнению "расширением" или "поддержкой для традиционной практики". * Если Вы - опытный пользователь инструментальных средств отладки, ваши предложения по улучшению GDB приветствуются в любом случае. - 203 - 17.2. Как составлять сообщения о дефектах Множество компаний и частных лиц предлагают поддержку для программных продуктов GNU. Если Вы получили GDB из поддерживающей нас организации, мы рекомендуем Вам сперва войти в контакт с ней. Вы можете найти информацию по контактам со многими поддерживающими нас компаниями и частными лицами в файле `etc/SERVICE' в дистрибутивах GNU Emacs. В любом случае, мы также рекомендуем посылать сообщения о дефектах GDB на один из этих адресов: bug-gdb@prep.ai.mit.edu {ucbvax|mit-eddie|uunet}!prep.ai.mit.edu!bug-gdb *Не посылайте сообщения о дефектах в `info-gdb', или `help-gdb', или в какую-нибудь группу новостей(newsgroup).* Большинство пользователей GDB не хотят получать сообщения о дефектах. Тем, кто хочет, обеспечивается получение `bug-gdb'. Список отправлений `bug-gdb' имеет группа новостей `gnu.gdb.bug', которая служит как повторитель. Список отправлений и группа новостей имеют одинаковые сообщения. Часто люди думают послать сообщения о дефектах в группу новостей по обычной почте вместо отправки по сети. Это срабатывает, но имеется одна проблема, которая может быть критической: группа новостей часто отправляет недостаточную информацию обратно отправителю. Таким образом, если мы должны запросить большую информацию, мы можем не иметь возможности достать Вас. По этой причине, лучше посылать сообщения о дефектах в список отправлений. И наконец, посылайте сообщения о дефектах по адресу: GNU Debugger Bugs Free Software Foundation Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307 USA - 204 - Фундаментальный принцип действенного составления сообщений о дефектах: сообщайте все факты. Если Вы не уверены, оставить факт или исключить, оставьте его! Часто люди опускают факты, потому что думают, что знают причины проблемы, и полагают, что некоторые детали не имеют значения. Таким образом, Вы можете считать, что имя переменной, которую Вы используете в примере, не имеет значения. Возможно, это так, но нельзя быть уверенным в этом. Возможно, дефект - обращение к памяти, которое выбрало данные из ячейки, где хранилось это имя; возможно, если имя будет другим, содержание этой ячейки введет отладчик в заблуждение, и дефект не будет замечен. Относитесь к этому осторожно, и давайте определенные, полные примеры. Это самое простое и наиболее полезное, что вы можете сделать. Имейте в виду, что цель сообщенияа о дефектах состоит в том, чтобы дать нам возможность установить дефект, если он нам не известен. Следовательно, всегда делайте сообщения о дефектах при условии, что о дефекте не было сообщено ранее. Иногда люди дают несколько поверхностных фактов и спрашивают, не говорит ли это о дефекте. Такие сообщения о дефектах бесполезны, и мы сообщаем всем, что отказываемся отвечать на такие послания. Чтобы дать нам возможность установить дефект, Вы должны включить в сообщение следующее: * Версия GDB. GDB объявляет ее при запуске без параметров; Вы можете также вывести ее, используя `show version'. Без этого мы не будем знать, имеет ли смысл поиск дефекта в текущей версии GDB. * Тип машины, на которой Вы работаете, и название операционной системы и номер ее версии. - 205 - * Какой компилятор (и его версия) использовался, чтобы компилировать GDB - например "gcc-2.0". * Какой компилятор (и его версия) использовался для компиляции отлаживаемой программы, - например "gcc-2.0". * Параметры команды, которую Вы дали компилятору, чтобы компилировать ваш пример и наблюдать дефект. Например, использовали ли вы `-O'? Для гарантии, что не будет опущено что-нибудь важное, перечисляйте все. Копии Makefile (или вывода после компиляции) достаточно. Если Вы не сообщите нам эти параметры, мы можем предположить их неправильно и тогда не столкнемся с дефектом. * Полное описание ввода, и все необходимые исходные файлы, которые воспроизведут дефект. * Описание поведения, которое Вы наблюдаете, что, по вашему мнению, неправильно. Например, "Это приводит к фатальному сигналу." Конечно, если дефект состоит в том, что GDB получает фатальный сигнал, тогда мы, конечно, заметим это. Но если дефект - некорректный вывод, мы можем не заметить этого, если это не бросается в глаза. Т.о. Вы могли бы не дать нам возможности ошибиться. Даже если ваша проблема в фатальном сигнале, Вы должны сообщать об этом явно. Предположим, происходит что-то необычное, например, ваша копия GDB рассинхронизировалась или Вы столкнулись с ошибкой в библиотеке C вашей системы. (Это случается!) Ваша копия может разрушиться, а наша нет. Если Вы предупредите нас, где ожидать аварию, а наша система не разрушится, мы будем знать, что у нас дефекта нет. Если Вы не предупредите нас, мы не сможем сделать вывод из наших наблюдений. - 206 - * Если Вы хотите предложить внести изменения в источник GDB, присылайте нам изменения контекста. Если Вы желаеете обсудить что-нибудь из источника GDB, ссылайтесь по контексту, а не по номеру строки. Номера строк в наших источниках разработки могут не соответствовать вашим источникам. Ваши номера строк не дадут нам никакой полезной информации. Теперь некоторые вещи, не являющиеся необходимыми: * Описание контекста дефекта. Часто те, кто сталкиваются с дефектом, тратят много времени на исследования, какие изменения входного файла приведут к исчезновению дефекта, а какие не влияют на него. Это часто не самое полезное времяпрепровождение, потому что мы найдем дефект посредством выполнения одного примера под отладчиком с точками останова, а не чистыми выводами из последовательности примеров. Мы рекомендуем вам поберечь ваше время на что-нибудь еще. Конечно, нам удобнее исследовать как можно более простой пример. Будет проще выделение ошибок в выводе, выполнение под отладчиком будет занимать меньше времени и так далее. Однако, такого рода упрощение не является жизненно необходимым; если Вы не хотите делать этого, сообщайте о дефекте в любом случае и посылайте нам весь тестовый случай, который Вы использовали. * Исправления ошибок. Ваши варианты исправления обнаруженных дефектов помогут нам, если они хорошие. Но в любом случае присылайте нам всю сопутствующую информацию (тестовый пример), даже если вы твердо уверены, что предложенные вами исправления - все, что нам нужно. Мы могли бы - 207 - рассмотреть проблему вместе с вашими исправлениями и решить установить проблему другим путем (в худшем случае, мы можем вообще не понять сути ваших предложений). Иногда для сложной программы (такой, как GDB) очень трудно создать пример, который заставит программу выполниться определенным образом. Если Вы не пришлете нам пример, мы не сможем сконструировать его сами и тем самым не сможем убедиться, что дефект устранен. И если мы не сможем понять, какой дефект Вы пытаетесь исправить или почему ваши исправления являются улучшением, мы не будем включать их в инсталяционную версию. Тестовый случай поможет нам все понять. * Предположения, что это за дефект, или от чего он зависит. Такие предположения обычно неверны. Мы не сможем сделать даже правильных предположений о такого рода вещах до запуска отладчика для выявления фактов. Приложение А. Редактирование командной строки Здесь описывается GNU-интерфейс редактирования командной строки. А.1. Введение Ниже описываются обозначения, которые мы используем для обозначения нажатия клавиш. Текст C-k читается как `Control-K' и описывает литеру, введенную нажатием клавиши k при утопленной клавише Control . Текст M-k читается как `Meta-K' и описывает литеру, введенную нажатием клавиши k при утопленной мета-клавише (если она имеется). Если мета-клавиши нет, сгенерировать ту же литеру можно, нажав сначала - 208 - клавишу ESC и затем k. Такой процесс называется метафикацией клавиши k. Текст M-C-k читается как `Meta-Control-k' и описывает литеру, произведенную посредством метафикации C-k. Кроме того, несколько клавиш имеют собственные имена. DEL, ESC, LFD, SPC, RET и TAB в этом тексте (или в файле инициализации) обозначают именно эти клавиши. Для получения большей информации, см.Раздел А.3 [Файл инициализации Readline]. А.2. Взаимодействие с Readline Часто во время интерактивного сеанса Вы вводите длинную строку текста, а потом замечаете, что в первом слове допущена орфографическая ошибка. Библиотека Readline предоставляет Вам набор команд для управления текстом во время ввода, позволяя Вам не перебивать большую часть строки. С помощью этих команд Вы перемещаете курсор в место, требующее исправления, и удаляете или вставляете текст. Затем, когда строка полностью исправлена, Вы просто нажимаете RET; вся строка вводится независимо от расположения курсора в ее пределах. А.2.1. Клавиши первой необходимости Для ввода литеры в строку нужно просто нажать ее. Печатаемая литера появляется там, где был курсор, и затем курсор перемещается на одну позицию вправо. Если Вы неверно набрали литеру, Вы можете использовать DEL, чтобы вернуться и удалить ее. Иногда Вы можете пропустить литеру, которую хотели набрать, и заметить это, когда уже напечатаете несколько других литер. В этом случае Вы можете нажать C-b, чтобы переместить курсор влево, и исправить ошибку. После этого Вы можете нажатием C-f переместить курсор вправо. - 209 - Когда Вы добавляете текст в середину строки, литеры справа от курсора 'сдвигаются вперед', чтобы освободить место для вставляемого текста. Аналогично, когда Вы удаляете текст перед курсором, литеры справа от него 'сдвигаются назад', занимая пустое пространство. Ниже следует список основных клавиш первой необходимости для редактирования вводимого текста. C-b Возврат на одну позицию. C-f Сдвиг вперед на одну позицию. DEL Удаление литеры слева от курсора. C-d Удаление литеры в позиции курсора. Нажатие литерных клавиш Вставка литер в строку по курсору. C-_ Отменяет последнее выполненное действие. Вы можете отменить все до опустошения строки. А.2.2. Команды перемещения Выше описаны только самые базовые клавиши, которые могут вам понадобиться при редактировании вводимой строки, но в дополнение к ним существуют и другие. Например, команды для более быстрого перемещения вдоль строки. C-a Перемещение в начало строки. - 210 - C-e Перемещение в конец строки. M-f Перемещение вперед на слово. M-b Перемещение назад на слово. C-l Очистка экрана с перепечатыванием текущей строки вверху экрана. Замечание: тогда как C-f перемещает курсор вперед на позицию, M-f перемещает его на слово. Соблюдается негласное соглашение, что нажатия клавиши Сontrol оперируют над позициями, в то время как нажатия мета-клавиши оперируют словами. А.2.3. Команды уничтожения "Уничтожение" текста означает удаление текста из строки, но сохранение его для дальнейшего использования (обычно вставки обратно в строку). Если в описании команды сказано, что она `уничтожает' текст, то позже можно вставить его обратно в другое (или это же) место. Здесь приведен список команд уничтожения текста. C-k Уничтожает текст с текущей позиции курсора до конца строки. M-d Уничтожает от курсора до конца текущего слова или, если курсор находится между словами, до конца следующего слова. M-DEL Уничтожает от курсора до начала текущего слова или, если курсор находится между словами, до начала предыдущего слова. - 211 - C-w Уничтожает от курсора до предыдущего пробела. Отличается от M-DEL, т.к. границы слова различаются. Ниже описано, как можно вставить текст обратно в строку. C-y Вставка последнего уничтоженного текста в позицию курсора. M-y Циклический сдвиг по списку уничтожений и вставка новой вершины списка. Вы можете использовать ее, только если предыдущая команда была C-y или M-y. Когда Вы используете команду уничтожения, текст сохраняется в списке уничтожений. При любом числе последовательных уничтожений весь уничтожаемый текст сохраняется вместе, так чтобы при его вставке, Вы бы получили его в одной развертке. Список уничтожений не зависит от строки; текст, который Вы уничтожили в предыдущей строке, доступен для вставки при наборе другой строки. А.2.4. Параметры команд Readline Вы можете передавать числовые параметры командам Readline. Иногда параметр означает повтор, иногда он указывает направление действия команды. Например, если Вы передаете отрицательный параметр команде, которая обычно действует в прямом направлении, то она будет действовать в обратном направлении. (Чтобы уничтожить текст до начала строки, Вы можете набрать M- C-k.) Основной способ передачи числовых параметров команде состоит в наборе мета-цифр перед командой. Если первая набранная 'цифра' - знак минуса (-), тогда знак параметра будет отрицательным. Если Вы набрали одну мета-цифру - начало параметра - Вы можете набрать оставшиеся цифры, и потом команду. Например, чтобы дать команде C-d параметр 10, Вы можете набрать M-1 0 C-d. - 212 - А.3. Файл инициализации Readline Хотя библиотека Readline поставляется с установками обработки клавиш, подобными установкам GNU Emacs, Вы, возможно, захотите пользоваться другими вариантами обработки клавиш. Вы можете настраивать программы, которые используют Readline, помещая команды в файл инициализации в вашем домашнем каталоге. Имя этого файла - '~/.inputrc'. Когда запускается программа, которая использует библиотеку Readline, читается файл '~/.inputrc' и устанавливается обработка клавиш. Кроме того, команда C-x C-r перечитывает этот файл инициализации, так что подключаются любые изменения, которые Вы cделали к этому времени. А.3.1. Синтаксис инициализации Readline Существуют только четыре конструкции, которые позволяется использовать в файле `~/.inputrc': Установка переменных Вы можете изменять состояния нескольких переменных в Readline. Это делается посредством использования команды `set' в файле инициализации. Далее указано, как определить то, что Вы желаете использовать команды `vi' редактирования строки : set editing-mode vi Существует немного переменных, которые могут быть установлены; фактически так мало, что мы просто их здесь перечислим: `editing-mode' Переменная `editing-mode' контролирует, какой режим редактирования Вы используете. По умолчанию, GNU Readline запускается в режиме редактирования Emacs, где нажатия - 213 - клавиши наиболее сходны с Emacs. Эта переменная может также быть установлена в `emacs' или `vi'. `horizontal-scroll-mode' Эта переменная может быть установлена в `On' или `Off'. Установка в `On' означает, что текст в строках, которые Вы редактируете, будет прокручиваться горизонтально, когда строки больше ширины экрана, вместо переноса на новую строку. По умолчанию, эта переменная установлена в `Off'. `mark-modified-lines' Эта переменная, будучи установлена в `On', указывает, что в начале измененных строк в архиве, отображается звездочка (`*'). По умолчанию установлена в `Off'. `prefer-visible-bell' Если эта переменная установлена в `On', это означает, что используется видимый сигнал оповещения(bell), если он доступен, вместо простого терминального звуковго сигнала. По умолчанию, значение `Off'. Установки обработки клавиш Синтаксис для управления установками обработки клавиш в файле `~/.inputrc' прост. Во-первых, Вы должны знать имя команды, которую Вы хотите изменить. Ниже приводятся имена команд, установки обработки по умолчанию, и краткое описание действий команд. Если Вы знаете имя команды, просто поместите в строку файла `~/.inputrc' название клавиши, которую Вы желаете связать с командой, двоеточие, и затем имя команды. Название клавиши может быть выражено различными способами в зависимости от удобства. KEYNAME: FUNCTION-NAME or MACRO KEYNAME - название клавиши, записанное по-английски. Например: - 214 - Control-u: universal-argument Meta-Rubout: backward-kill-word Control-o: ">&output" В вышеупомянутом примере, C-u связана с функцией `universal-argument', а C-o связана с выполнением макрокоманды, которая вставляет текст `>&output' в строку). "KEYSEQ": FUNCTION-NAME or MACRO KEYSEQ отличается от KEYNAME тем, что может определять строки, обозначающие целую ключевую последовательность. Просто поместите ключевую последовательность в двойных кавычках. Могут использоваться управляющие клавиши в стиле GNU Emacs, например: "\C-u": universal-argument "\C-x\C-r": re-read-init-file "\e[11~": "Function Key 1" В вышеупомянутом примере, C-u связана с функцией `universal-argument' (как в первом примере), C-x C-r связана с функцией `re-read-init-file' и ESC [ 1 1 ~ связана со вставкой текста `Function Key 1'. А.3.1.1. Команды для перемещения по тексту `beginning-of-line (C-a)' Перемещение в начало текущей строки. `end-of-line (C-e)' Перемещение в конец строки. `forward-char (C-f)' Перемещение на одну позицию вперед. `backward-char (C-b)' Возврат на одну позицию. - 215 - `forward-word (M-f)' Перемещение вперед до конца следующего слова. `backward-word (M-b)' Возврат к началу этого, или предыдущего, слова. `clear-screen (C-l)' Очистка экрана с оставлением текущей строки вверху экрана. А.3.1.2. Команды манипуляции архивом `accept-line (Newline, Return)' Ввод строки независимо от расположения курсора. Если строка непуста, добление ее к архивному списку. Если эта строка была строкой архива, восстановление строки архива в первоначальном состоянии. `previous-history (C-p)' Перемещение вверх по архивному списку. `next-history (C-n)' Перемещение вниз по архивному списку. `beginning-of-history (M-<)' Перемещение в начало архивного списка. `end-of-history (M->)' Перемещение в конец архива ввода, т.е. к строке, которую Вы ввели. `reverse-search-history (C-r)' Обратный поиск, начиная с текущей строки, вверх по архиву. Это - инкрементный поиск. `forward-search-history (C-s)' Прямой поиск, начиная с текущей строки, вниз по архиву. - 216 - А.3.1.3. Команды для изменения текста `delete-char (C-d)' Удаление литеры в позиции курсора. EOF, если курсор находится в начале строки, строка пуста и последняя набранная литера была не C-d. `backward-delete-char (Rubout)' Удаление литеры перед курсором. Числовой параметр предписывает уничтожать литеры, а не удалять их. `quoted-insert (C-q, C-v)' Добавление в строку следующей литеры, какой бы она ни была. Таким образом вставляется, например, C-q. `tab-insert (M-TAB)' Вставка табуляции. `self-insert (a, b, A, 1, !, ...)' Самостоятельная вставка. `transpose-chars (C-t)' Переставить местами литеру перед отметкой и литеру на отметке. Отметка перемещается вперед. Если отметка находится в конце строки, переставляются две литеры перед отметкой. `transpose-words (M-t)' Переставить местами слово перед курсором и слово за ним. Курсор перемещается за эти слова. `upcase-word (M-u)' Обращение в верхний регистр всех литер в текущем (или последующем) слове. С отрицательным параметром обращает литеры предыдущего слова, но не перемещает отметку. - 217 - `downcase-word (M-l)' Обращает в нижний регистр все литеры в текущем (или последующем) слове. С отрицательным параметром обращает литеры предыдущего слова, но не перемещает отметку. `capitalize-word (M-c)' Обращает в верхний регистр первую литеру в текущем (или последующем) слове. С отрицательным параметром обращает первую литеру предыдущего слова, но не перемещает отметку. А.3.1.4. Уничтожение и вставка `kill-line (C-k)' Уничтожение текста с текущей позиции курсора до конца строки. `backward-kill-line ()' Уничтожение до начала строки. С определенной клавишией обычно не связывается. `kill-word (M-d)' Уничтожение с текущей позиции курсора до конца текущего слова, или, если курсор находится между словами, до конца следующего слова. `backward-kill-word (M-DEL)' Уничтожение слова перед курсором. `unix-line-discard (C-u)' Уничтожение целой строки посредством C-u, используемой в Unix line input. Уничтоженный текст сохраняется в списке уничтожений. `unix-word-rubout (C-w)' Уничтожение слова посредством C-w, используется в Unix-формате ввода строк. Уничтоженный текст сохраняется в списке уничтожений. Команда отличается от backward-kill-word тем, что границы слова различаются. - 218 - `yank (C-y)' Вставка вершины списка уничтожений в буфер на отметке. `yank-pop (M-y)' Циклический сдвиг списка уничтожений, и вставка новой вершины списка уничтожений. Вы можете использовать команду, только если предыдущая команда - yank или yank-pop. А.3.1.5 Спецификация числовых параметров `digit-argument (M-0, M-1, ... M--)' Добавляет цифру к вводимому параметру или начинает новый параметр. M- начинает отрицательный параметр. `universal-argument ()' Делает то, что в GNU Emacs делает C-u. По умолчанию не связывается с определенной клавишей. А.3.1.6. Возможности Readline ввода для Вас `complete (TAB)' Попытка завершения текста перед отметкой. Производит определенное выполнение. В принципе, если Вы вводите параметр имени файла, Вы можете завершить имя файла; если Вы вводите команду, можете завершить ее; если вводите символ для GDB, можете завершить его имя; если вводите переменную для Bash, можете завершить имя переменной. `possible-completions (M-?)' Список возможных завершений текста перед отметкой. - 219 - А.3.1.7. Прочие команды `re-read-init-file (C-x C-r)' Читает содержание вашего файла `~/.inputrc', и подключает любые найденные там сведения по обработке клавиш. `abort (C-g)' Остановка выполнения текущей команды редактирования. `prefix-meta (ESC)' Метафицировать следующую введенную Вами литеру. Команда полезна, если мета-клавиша отсутствует. Набор ESC f эквивалентен набору M-f. `undo (C-_)' Инкрементная отмена, отдельно запоминающаяся для каждой строки. `revert-line (M-r)' Отмена всех изменений, сделанных в строке. Команда подобна `undo', выполненной достаточное число раз. А.3.2. `Vi'-режим Readline Хотя библиотека Readline не имеет полного набора `vi'-функций редактирования, она содержит достаточно для простого редактирование строки. Переключение в интерактивном режиме между GNU Emacs- и `vi'-режимами редактирования осуществляется с помощью команды M-C-j (toggle-editing-mode). Когда Вы вводите строку в `vi'-режиме, Вы находитесь в режиме вставки, как если бы Вы набрали `i'. Нажатие ESC переключит Вас в режим редактирования, в котором Вы можете редактировать текст строки стандартными клавишами перемещения `vi', продвигаться к предыдущим строкам архива посредством `k', к последующим строкам посредством `j', и т.д. - 220 - Приложение Б. Использование архива в интерактивном режиме В этой главе описывается, как использовать библиотеку GNU History в интерактивном режиме c точки зрения пользователя. Б.1. Взаимодействие с History Библиотека History обеспечивает средства расширения архива подобно расширению архива в `csh'. Ниже описывается синтаксис, использующийся для манипулирования с информацией архива. Расширение архива состоит из двух частей. В первой части определяется, какая из строк предыдущего архива будет использоваться для замены. Эта строка называется "событием". Во второй части выбираются куски этой строки для включения в текущую строку. Эти куски называются "словами". GDB разбивает строку на слова так же, как Bash, например, несколько английских (или Unix-) слов, заключенных в кавычки, рассматриваются как одно слово. Б.1.1. Указатели события "Указатель события" является ссылкой на запись командной строки в архивном списке. `!' Начать архивное замещение, если только `!' не сопровождается пробелом, табуляцией, или знаком конца строки... = или (. `!!' Ссылка на предыдущую команду. `!!' - синоним `!-1'. `!n' Ссылка на командную строку под номером N. - 221 - `!-n' Ссылка на командную строку, расположенную на N строк назад. `!string' Ссылка на самую последнюю команду, начинающейся со STRING. `!?string'[`?'] Ссылка на самую последнюю команду, содержащую STRING. Б.1.2. Указатели слова Указатель события от `указателя слова' отделяется двоеточием (`:'). Его можно опустить, если указатель слова начинается с литер ^, $, * или %. Слова нумеруются от начала строки, первому слову дается номер 0 (ноль). `0 (zero)' Нулевое слово, обычно управляющее. `n' N-ное слово. `^' Первый параметр. То есть слово 1. `$' Последний параметр. `%' Слово, соответствующее последнему поиску `?string?'. `x-y' Диапазон слов; `0-Y' сокращается до `-Y'. `*' Все слова, за исключением нулевого. Это - синоним `1-$'. Даже если имеется только одно слово в `событии', использование * не - 222 - является ошибкой. В этом случае возвращается пустая строка. Б.1.3. Модификаторы После возможно отсутствующего указателя слова, Вы можете добавить последовательность из одного или более нижеследующих "модификаторов", каждый из которых начинается с двоеточия. `#' Вывести командную строку. Подразумевается текущая, а не предыдущая команда. `h' Удалить конечную компоненту имени пути, оставляя только начальную. `r' Удалить конечный суффикс формы `.'SUFFIX, оставляя базовое имя. `e' Удалить все, кроме суффикса. `t' Удалить все начальные компоненты имени пути, оставляя хвост. `p' Вывести новую команду, не выполняя ее. Приложение В. Форматирование документации GDB 4 содержит уже отформатированную справочную карту, готовую к печати с PostScript или Ghostscript, в подкаталоге `gdb' главного каталога (в версии 4.15 - в gdb-4.15/gdb/refcard.ps). Если Вы можете использовать PostScript или Ghostscript на вашем принтере, можете печатать справочную карту немедленно из `refcard.ps'. - 223 - GDB 4 также включает исходник справочной карты. Вы можете форматировать ее, используя TeX, набрав make refcard.dvi Справочная карта GDB разработана для печати в режиме "landscape" на бумаге размера US "letter"; то есть на листе шириной 11 дюймов и высотой 8.5 дюймов. Вы будете должны определить этот формат печати опцией вашей DVI программы вывода. Вся документация для GDB поставляется как часть машинно-считываемых дистрибутивов. Документация написана в формате Texinfo, который является документационной системой, использующей один исходный файл, чтобы создать интерактивную информацию и печатное руководство. Вы можете использовать одну из форматирующих команд Info, чтобы создать интерактивную версию документации, и TeX (или `texi2roff') для печати печатной версии. GDB включает уже отформатированную копию интерактивной версии Info этого руководства в подкаталоге `gdb'. Основной файл Info - `gdb-version-number/gdb/gdb.info', он обращается к файлам, соответствующим `gdb.info*', в том же каталоге. В случае необходимости Вы можете распечатать эти файлы, или читать их в любом редакторе; но их легче прочитать, используя подсистему `info' в GNU Emacs или автономную `info' программу, доступную как часть дистрибутивов GNU Texinfo. Если Вы хотите форматировать эти Info файлы самостоятельно, Вам нужна одна из программ форматирования Info, типа `texinfo-format-buffer' или `makeinfo'. Если у Вас установлена `makeinfo', и вы находитесь на верхнем уровне каталога GDB (`gdb-4.15', в случае версии 4.15), Вы можете cоздать файл Info, набрав cd gdb make gdb.info - 224 - Если Вы хотите распечатать копии этого руководства, Вам нужен TeX, программа печати DVI выходных файлов и файл определений Texinfo `texinfo.tex'. TeX - программа набора; она не печатает файлы непосредственно, но создает DVI выходные файлы. Чтобы напечатать набранный документ, Вам нужна программа печати DVI файлов. Если в вашей системе установлен TeX, возможно, он имеет такую программу. Какую точно команду нужно использовать зависит от вашей системы; `lpr -d' является общей; для PostScript устройств - `dvips'. Команда печати DVI может потребовать имя файла без расширения или с расширением `.dvi'. TeX также требует файл макроопределений `texinfo.tex'. Этот файл сообщает TeX, как набранный документ записан в формате Texinfo. TeX не может самостоятельно читать или печатать Texinfo файл. `texinfo.tex' устанавливается с GDB и размещается в каталоге `gdb-VERSION-NUMBER/texinfo'. Если у Вас установлен TeX и программа принтера DVI, Вы можете печатать это руководство. Сначала переключитесь в подкаталог `gdb' главного исходного каталога (например, в `gdb-4.15/gdb') и наберите: make gdb.dvi Приложение Г. Установка GDB GDB поставляется вместе с описанием конфигурации, которое автоматизирует подготовку GDB к инсталляции; тогда вы можете использовать `make' для построения программы `gdb'. Дистрибутивы GDB включают весь исходный код, который вам понадобится, в одном каталоге, имя которого обычно составляется добавлением номера версии к `gdb'. Например, дистрибутивы GDB версии 4.15 находятся в каталоге `gdb-4.15'. Этот каталог содержит: - 225 - `gdb-4.15/configure (and supporting files)' конфигурация GDB и все поддерживаемые библиотеки `gdb-4.15/gdb' неосредственно источник GDB `gdb-4.15/bfd' источник для библиотеки Binary File Descriptor `gdb-4.15/include' подключаемые файлы GNU `gdb-4.15/libiberty' источник для `-liberty' библиотеки свободного программного обеспечения `gdb-4.15/opcodes' источник для библиотеки таблиц кодов операций и дизассемблеров `gdb-4.15/readline' источник для GNU-интерфейса командной строки `gdb-4.15/glob' источник для подпрограммы GNU сопоставления с образцом имени файла `gdb-4.15/mmalloc' источник для карты распределения памяти пакета GNU Самый простой способ сконфигурировать и построить GDB состоит в выполнении `configure' из исходного каталога `gdb-VERSION-NUMBER'. Сначала войдите в каталог `gdb-VERSION-NUMBER', если вы находитесь не в нем; затем запустите `configure'. Передайте в качестве параметра идентификатор платформы, на которой запускается GDB. - 226 - Например: cd gdb-4.15 ./configure HOST make где HOST - идентификатор платформы, на которой запускается GDB, такой как `sun4' или `decstation'. (Вы можете опустить HOST; `configure' попытается предположить корректное значение проверкой вашей системы.) Выполнением `configure HOST' и `make' строятся сначала `bfd', `readline', `mmalloc' и `libiberty' библиотеки, а затем непосредственно `gdb'. Исходные файлы, а также построенные из них двоичные, остаются в соответствующих каталогах. `configure' является скриптом оболочки Bourne (`/bin/sh'); если ваша система не распознает его автоматически, когда вы запускаете другую оболочку, вам можете явно выполнить в ней `sh': sh configure HOST Если вы выполняете `configure' для нескольких библиотек или программ из каталога, который содержит каталоги с источниками, например, `gdb-4.15' для версии 4.15, `configure' создает файлы конфигурации для каждого уровня подкаталогов (если вы не запрещаете делать это опцией `--norecursion'). Вы можете выполнить `configure' из любого подкаталога GDB, если вы хотите сконфигурировать этот подкаталог, но убедитесь, что к `configure' указан путь. Например, для версии 4.15, чтобы сконфигурировать только подкаталог `bfd' наберите: cd gdb-4.15/bfd ../configure HOST - 227 - Вы можете устанавливать `gdb' где угодно, нет никаких аппаратных ограничений. Однако, Вы должны удостовериться, что ваша оболочка (назначаемая системной переменной `SHELL') доступна для чтения. Помните, что GDB использует оболочку для запуска вашей программы; некоторые системы не позволяют GDB отлаживать дочерние процессы неудобочитаемых программ. Г.1. Компилирование GDB в другом каталоге Если вы хотите запускать GDB на нескольких головных или целевых машин, вам нужны различные компиляции `gdb' для каждой комбинации головной и целевой машины. `configure' разработан, чтобы облегчить это, позволяя вам генерировать каждую конфигурацию в отдельном подкаталоге, а не в исходном каталоге. Если ваша программа `make' поддерживает особенности `VPATH'(`make' GNU делает это), она при запуске в каждом из этих каталогов строит программу `gdb', определенную там. Чтобы построить `gdb' в отдельном каталоге, запустите `configure' с опцией `--srcdir' для определения, где искать источник. (Вам также нужно определить путь к `configure' из рабочего каталога. Если путь к `configure' совпадает с параметром `--srcdir', опцию `--srcdir' можно опустить; она предполагается.) Например, в версии 4.15, Вы можете строить GDB в отдельном каталоге для Sun 4: cd gdb-4.15 mkdir ../gdb-sun4 cd ../gdb-sun4 ../gdb-4.15/configure sun4 make Когда `configure' строит конфигурацию, использующую отдаленный каталог с источниками, она строит дерево для двоичных файлов с той же структурой (и используя те же имена), что и дерево каталога с источниками. В примере вы бы нашли библиотеку Sun 4 `libiberty.a' в - 228 - каталоге `gdb-sun4/libiberty' и непосредственно GDB в `gdb-sun4/gdb'. Одна из распространенных причин построения нескольких конфигураций GDB в отдельных каталогах состоит в том, чтобы конфигурировать GDB для кросс-компиляции (когда GDB запускается на одной машине - `головной', в то время, как программы выполняются на другой машине - `целевой'). Вы определяете целевую машину кросс-отладки опцией `--target=TARGET' `configure'. Когда вы выполняете `make' для построения программы или библиотеки, вы должны выполнять ее в сконфигурированном каталоге - любом каталоге, из которого вы вызывали `configure' (или в одном из его подкаталогов). `Makefile', который генерирует `configure' в каждом каталоге с источниками, также выполняется рекурсивно. Если вы набрали `type' в каталоге с источниками, например, в `gdb-4.15' (или в отдельно сконфигурированном каталоге посредством `--srcdir=DIRNAME/gdb-4.15'), вы построите все требуемые библиотеки и затем GDB. Когда вы имеете составные головные или целевые конфигурации в отдельных каталогах, вы можете запустить `make' для них параллельно (например, если они NFC-смонтированы на каждой головной машине); они не будут конфликтовать друг с другом. Г.2. Определение имен для головных и целевых машин Спецификации, используемые для головных и целевых машин в `configure', именуются по схеме наименования тремя частями, но поддерживаются также некоторые предопределенные сокращения. Полная схема наименования кодирует три фрагмента информации по следующему образцу: ARCHITECTURE-VENDOR-OS Например, Вы можете использовать сокращение `sun4' как параметр HOST, или как значение TARGET в опции `--target=TARGET'. Эквивалентное полное имя - `sparc-sun-sunos4'. - 229 - `configure', сопровождающий GDB, не обеспечивает никаких средств запроса вывода всех поддерживаемых имен головных и целевых машин или их сокращений. `configure' вызывает скрипт оболочки Bourne `config.sub' для отображения сокращений полных имен; при желании вы можете прочитать скрипт или использовать его для проверки ваших предположений о сокращениях, например: % sh config.sub sun4 sparc-sun-sunos4.1.1 % sh config.sub sun3 m68k-sun-sunos4.1.1 % sh config.sub decstation mips-dec-ultrix4.2 % sh config.sub hp300bsd m68k-hp-bsd % sh config.sub i386v i386-unknown-sysv % sh config.sub i786v Invalid configuration `i786v': machine `i786v' not recognized `config.sub' также находится в каталоге с источниками GDB (`gdb-4.15', для версии 4.15). Г.3. Опции `configure' Здесь приводится резюме опций `configure' и параметров, которые наиболее часто используются для построения GDB. `configure' также имеет несколько других опций, не представленных здесь. См.Info файл `configure.info': `What Configure Does' для полного описания `configure'. configure [--help] [--prefix=DIR] [--srcdir=DIRNAME] [--norecursion] [--rm] [--target=TARGET] HOST - 230 - Вы можете вводить опции с одним `-',а не `--', если хотите; но Вы можете сокращать имена опций, если Вы используете `--'. `--help' Отображает быстрое резюме, как вызвать `configure'. `-prefix=DIR' Конфигурирует источник, чтобы установить программы и файлы в каталоге `DIR'. `--srcdir=DIRNAME' * Предупреждение: использование этой опции требует GNU-программы `make' или `make', поддерживающей особенности `VPATH'.* Используйте эту опцию для создания конфигураций в каталогах, отдельных от исходного каталога GDB. Кроме всего прочего, вы можете использовать ее для построения (или монтирования) нескольких конфигураций одновременно в отдельных каталогах. `configure' записывает конфигурацию особых файлов в текущий каталог, но принимает меры, чтобы можно было использовать источники в каталоге DIRNAME. `configure' создает каталоги под рабочим каталогом параллельно с исходными каталогами под DIRNAME. `--norecursion' Конфигуровать только уровень каталога, где выполняется `configure'; не распространять конфигурацию на подкаталоги. `--rm' *Удалить* файлы, построенные иначе во время конфигурирования. `--target=TARGET' Конфигурировать GDB для кросс-отладки программ, выполняемых на определенном TARGET. Без этой опции GDB конфигурируется для отладки программ, выполняемых на той же машине (HOST), что и GDB. Не имеется никакого удобного способа сгенерировать список всех допустимых целевых машин. - 231 - `HOST ...' Конфигуровать GDB для выполнения на определенном HOST. Не имеется никакого удобного способа сгенерировать список всех допустимых HOST. `configure' принимает другие опции для совместимости с рекурсивным конфигурированием других средств GNU; но представленные здесь опции - единственные, которые затрагивают GDB или поддерживаемые им библиотеки. - 232 - С О Д Е Р Ж А Н И Е 1. Пример работы GDB 3 2. Вход и выход из GDB 9 2.1. Вызов GDB 9 2.1.1. Выбор файлов 10 2.1.2. Выбор режима 13 2.2. Выход из GDB 14 2.3. Команды Shell 15 3. Команды GDB 15 3.1. Командный синтаксис 16 3.2. Завершение команды 17 3.3. Получение справки 19 4. Выполнение программ под управлением GDB 22 4.1. Компилирование для отладки 23 4.2. Запуск вашей программы 24 4.3. Аргументы вашей программы 26 4.4. Рабочая среда вашей программы 26 4.5. Рабочий каталог вашей программы 28 4.6. Ввод-вывод вашей программы 29 4.7. Отладка запущенного процесса 30 4.8. Уничтожение порожденнного процесса 31 4.9. Дополнительная информация о процессе 32 4.10. Отладка программ с несколькими потоками 33 4.11. Отладка многопроцессных программ 36 5. Остановка и продолжение исполнения 37 5.1. Точки останова, точки наблюдения и исключительные ситуации 37 5.1.1. Установка точек останова 38 5.1.2. Установка точек наблюдения 43 5.1.3. Точки останова и исключительные ситуации 45 5.1.4. Удаление точек останова 46 5.1.5. Отключение точек останова 47 5.1.6. Условия останова 49 5.1.7. Списки команд точек останова 51 - 233 - 5.1.8. Меню точек останова 53 5.2. Продолжение исполнения и пошаговое выполнение 54 5.3. Сигналы 59 5.4. Остановка и запуск многопотоковых программ 61 6. Исследование процедурного стека 63 6.1. Процедурные секции 63 6.2. Цепочки вызовов 65 6.3. Выбор процедурной секции 66 6.4. Информация о процедурной секции 68 6.3 [Выбор процедурной секции]. 69 6.5. MIPS машины и функциональный стек 70 7. Исследование исходных файлов 70 7.1. Вывод строк исходного текста 71 7.2. Поиск в исходных файлах 74 7.3. Определение каталогов с исходными текстами 74 7.4. Исходный текст и машинный код 76 8. Исследование данных 78 8.1. Выражения 78 8.2. Программные переменные 80 8.3. Искусственные массивы 81 8.4. Форматы вывода 83 8.5. Исследование памяти 85 8.6. Автоматическое отображение 87 8.7. Установки вывода 90 8.8. Архив значений 97 8.9. Рабочие переменные 99 8.10. Регистры 101 8.11. Аппаратные средства поддержки вычислений с плавающей точкой 103 9. GDB и различные языки программирования 104 9.1. Переход с однго языка на другой 104 9.1.1. Соответствие расширений файлов и языков 105 9.1.2. Установка рабочего языка 106 9.1.3. Распознавание GDB исходного языка 106 9.2. Отображение языка 107 - 234 - 9.3. Проверка принадлежности типу и диапазону 108 9.3.1. Краткий обзор проверки соответствия типов 108 9.3.2. Краткий обзор проверки диапазона 110 9.4. Поддерживаемые языки 112 9.4.1. C и C++ 112 9.4.1.1. Операторы C и C++ 112 9.4.1.2. Константы C и C++ 116 9.4.1.3. Выражения C++ 117 9.4.1.4. Значения C и C++, используемые по умолчанию 119 9.4.1.5. Проверки принадлежности к типу и диапазону в C и C++ 119 9.4.1.6. GDB и C 119 9.4.1.7. Особенности GDB для C++ 120 9.4.2. Modula-2 121 9.4.2.1. Операторы 121 9.4.2.2. Встроенные функции и процедуры 124 9.4.2.3. Константы 127 9.4.2.4. Установки Modula-2 по умолчанию 128 9.4.2.5. Отклонения от стандарта Modula-2 128 9.4.2.6. Проверка Modula-2 принадлежности к типу и диапазону 129 9.4.2.7. Операторы определения области видимости `::' и `.' 130 9.4.2.8. GDB и Modula-2 130 10. Исследование таблицы символов 131 11. Выполнение с изменениями в программе 135 11.1. Присваивание значений пеpеменным 135 11.2. Продолжение выполнения с другого адреса 137 11.3. Подача сигнала вашей программе 138 11.4. Возврат из функции 139 11.5. Вызов функций программы 139 11.6. Внесение изменений в программу 140 12. Файлы GDB 141 12.1. Команды для определения файлов 141 12.2. Ошибки чтения символьных файлов 147 13. Определение отладочной цели 149 13.1. Активные цели 150 - 235 - 13.2. Команды управления целями 151 13.3. Выбор целевого порядка байтов 154 13.4. Дистанционная отладка 155 13.4.1. Отдаленный последовательный протокол GDB 155 13.4.1.1. Что заглушка может сделать для Вас 157 13.4.1.2. Что Вы должны сделать для заглушки 158 13.4.1.3. Помещение всего вместе 160 13.4.1.4. Протокол связи 162 13.4.1.5. Использование программы `gdbserver' 165 13.4.1.6. Использование программы `gdbserve.nlm' 167 13.4.2. GDB с удаленным i960 (Nindy) 169 13.4.2.1. Запуск с Nindy 169 13.4.2.2. Опции для Nindy 170 13.4.2.3. Команда сброса Nindy 171 13.4.3. UDI-протокол для AMD29K 171 13.4.4. EBMON-протокол для AMD29K 171 13.4.4.1 Установка соединений 172 13.4.4.2. Кросс-отладка EB29K 174 13.4.4.3. Отдаленный журнал 175 13.4.5. GDB с Tandem ST2000 175 13.4.6. GDB и VxWorks 176 13.4.6.1. Соединение с VxWorks 177 13.4.6.2. Загрузка в VxWorks 178 13.4.6.3. Выполняющиеся задачи 179 13.4.7. GDB и микропроцессоры Hitachi 179 13.4.7.1 Соединение с платами Hitachi 180 13.4.7.2. Использование внутрисхемного эмулятора E7000 180 13.4.7.3. Специальные команды GDB для микросхем Hitachi 181 13.4.8. GDB и удаленныe платы MIPS 181 13.4.9. Целевой имитируемый ЦП 184 14. Управление GDB 185 14.1. Приглашение 185 14.2. Редактирование команд 186 14.3. Архив команд 186 14.4. Размеp экpана 188 14.5. Числа 189 14.6. Необязательные предупреждения и сообщения 190 - 236 - 15. Фиксированные последовательности команд 192 15.1. Команды, определяемые пользователем 192 15.2. Определяемые пользователем команды-ловушки 194 15.3. Командные файлы 195 15.4. Команды управления выводом 196 16. Использование GDB под управлением GNU Emacs 198 17. Сообщения о дефектах GDB 202 17.1. Дефект ли Вы нашли? 202 17.2. Как составлять сообщения о дефектах 203 Приложение А. Редактирование командной строки 207 Приложение Б. Использование архива в интерактивном режиме 220 Приложение В. Форматирование документации 222 Приложение Г. Установка GDB 224
CC-BY-CA Анатольев А.Г., 31.01.2012