Этот раздел посвящен анализу, проверке и изменению данных в программах.
В этом разделе рассматриваются следующие вопросы:
Программа dbx может перехватывать или игнорировать сигналы, отправляемые в вашу программу. Каждый раз, когда в вашу программу отправляется сигнал, программа dbx получает об этом уведомление. Если сигнал следует проигнорировать, он передается в вашу программу; в противном случае dbx останавливает программу и сообщает о перехвате сигнала. Программа dbx не может проигнорировать сигнал SIGTRAP, если он поступил от внешнего по отношению к ней процесса. В программе с несколькими нитями сигнал может передаваться в определенную нить с помощью функции pthread_kill. По умолчанию программа dbx останавливается и сообщает о перехвате сигнала. С помощью команды ignore можно указать, что программа dbx должна игнорировать сигнал и передавать его нити. Для изменения режима обработки сигнала по умолчанию предназначены команды catch и ignore.
В следующем примере сигналы SIGGRANT и SIGREQUEST применяются программой для выделения ресурсов. Для того чтобы программа dbx продолжала работу при получении этих сигналов, введите:
(dbx) ignore GRANT (dbx) ignore SIGREQUEST (dbx) ignore CONT CLD ALARM KILL GRANT REQUEST
Если установить переменную $sigblock, то программа dbx будет блокировать сигналы, передаваемые в вашу программу. По умолчанию сигналы, поступающие в программу dbx, направляются в исходную программу или в объектный файл, определяемый параметром Объектный_файл программы dbx. Если с помощью команды set установить переменную $sigblock, то сигналы, получаемые программой dbx, не будут передаваться в исходную программу. Если вы хотите, чтобы сигнал передавался в программу, воспользуйтесь командой cont с сигналом в качестве операнда.
Можно использовать этот способ для прерывания выполнения программы, которая запускается программой dbx. Обычно перед продолжением выполнения программы проверяется ее состояние. Если переменная $sigblock не установлена, то при прерывании выполнения в программу передается сигнал SIGINT. При продолжении выполнения программы управление передается обработчику сигнала (если он существует).
Следующий пример программы показывает, как изменяется порядок выполнения при запуске в режиме отладки (т.е. с помощью dbx), если установлена переменная $sigblock:
#include <signal.h> #include <stdio.h> void inthand( ) { printf("\nПолучен сигнал SIGINT\n"); exit(0); }
main( ) { signal(SIGINT, inthand); while (1) { printf("."); fflush(stdout); sleep(1); } }
В следующем примере эта программа используется как исходный файл в сеансе работы с программой dbx. При первом прогоне программы переменная $sigblock не установлена. Во время повторного запуска (rerun) переменная $sigblock установлена. Справа в угловых скобках приведены комментарии:
dbx version 3.1. Введите 'help' для просмотра справки. чтение символьной информации ... (dbx) run .........^C <Здесь пользователь нажал Ctrl-C> прерывание в sleep в 0xd00180bc 0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1) (dbx) cont
получен SIGINT
выполнение завершено (dbx) set $sigblock (dbx) rerun [ looper ] ..............^C <Здесь пользователь нажал Ctrl-C> прерывание в sleep в 0xd00180bc 0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1) (dbx) cont ....^C <Программа не получила сигнал, выполнение продолжается>
прерывание в sleep в 0xd00180bc 0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1) (dbx) cont 2 <Завершение программы с сигналом 2>
получен SIGINT
выполнение завершено (dbx)
Из программы dbx можно вызывать процедуры для тестирования различных аргументов. Можно также вызывать диагностические процедуры, которые форматируют данные для упрощения отладки. Для вызова процедуры служит команда call или команда print.
Для просмотра списка вызовов процедур, которые предшествовали останову программы, служит команда where.
В приведенном ниже примере исполняемый объектный файл hello состоит из двух исходных файлов и трех процедур, включая стандартную процедуру main. Программа останавливается в точке прерывания в процедуре sub2.
(dbx) run [1] останавливается в sub2 в строке 4 в файле "hellosub.c" (dbx) where sub2(s = "hello", n = 52), строка 4 в "hellosub.c" sub(s = "hello", a = -1, k = delete), строка 31 в "hello.c" main(), строка 19 в "hello.c"
При трассировке стека вызовы просматриваются в обратном порядке. Если начать с дна стека, то происходившие события образуют следующую последовательность:
Примечание: Для того чтобы отключить режим вывода на экран аргументов, передаваемых в процедуры, задайте в программе отладки переменную $noargs.
С помощью команд up и down можно просматривать фрагменты стека.
Для просмотра выражений применяется команда print. Для печати имен и значений переменных - команда dump. Если данная процедура - точка, то печатаются все активные переменные. Для изменения значения переменной предназначена команда assign.
В приведенном ниже примере в программе на языке C используются автоматическая целочисленная переменная x со значением 7 и параметры s и n в процедуре sub2:
(dbx) print x, n 7 52 (dbx) assign x = 3*x (dbx) print x 21 (dbx) dump sub2(s = "hello", n = 52) x = 21
Для просмотра информации о пользовательских нитях, взаимных блокировках, условиях и объектах атрибутов предназначены команды thread, mutex, condition и attribute. К этим объектам применима также команда print. В следующем примере выполняется нить 1. Пользователь делает текущей нить 2, запрашивает список нитей, печатает информацию о нити 1 и, наконец, печатает информацию о нескольких объектах, связанных с нитями.
(dbx) thread current 2 (dbx) thread thread state-k wchan state-u k-tid mode held scope function *$t1 run running 12755 u no pro main >$t2 run running 12501 k no sys thread_1
(dbx) print $t1 (thread_id = 0x1, state = run, state_u = 0x0, tid = 0x31d3, mode = 0x1, held = 0x0, priority = 0x3c, policy = other, scount = 0x1, cursig = 0x5, attributes = 0x200050f8)
(dbx) print $a1,$c1,$m2 (attr_id = 0x1, type = 0x1, state = 0x1, stacksize = 0x0, detachedstate = 0x0, process_shared = 0x0, contentionscope = 0x0, priority = 0x0, sched = 0x0, inherit = 0x0, protocol = 0x0, prio_ceiling = 0x0) (cv_id = 0x1, lock = 0x0, semaphore_queue = 0x200032a0, attributes = 0x20003628) (mutex_id = 0x2, islock = 0x0, owner = (nil), flags = 0x1, attributes = 0x200035c8)
Для преобразования имен в первую очередь применяется статический контекст текущей функции. Динамический контекст используется в том случае, если имя не определено в статическом контексте. Если имя не найдено ни в статическом, ни в динамическом контексте, то выбирается произвольный символ и печатается сообщение usingQualifiedName. Можно переопределить процедуру преобразования имен, задав идентификатор и имя блока (например, Модуль.Переменная). Исходные файлы рассматриваются как модули, имена которых совпадают с именами файлов без расширения. Например, полное имя переменной x, объявленной в процедуре sub внутри файла hello.c, будет hello.sub.x. Точка в имени ставится самой программой.
При наличии нескольких символов с одним именем для того чтобы определить, какой именно символ найден, можно воспользоваться командами which и whereis.
Программа dbx позволяет
просматривать широкий диапазон выражений. Для задания выражений
используется обычный синтаксис языка C или Pascal, с некоторыми расширениями
языка FORTRAN.
В выражениях допустимы следующие
типы операций:
Логические операции и операции сравнения разрешается использоваться для записи условий в командах stop и trace.
Программа dbx контролирует типы выражений. Вы можете переопределять тип выражения с помощью оператора переименования или приведения типа. Существуют три способа переименования типа:
Примечание: Если исходным или целевым типом при приведении является структура, объединение или класс, то выполняется выравнивание влево. Однако при приведении класса к базовому классу соблюдаются синтаксические правила языка C++.
Например, для переименования переменной x целого типа со значением 97 введите:
(dbx) print char (x), x \ char, (char) x, x, 'a' 'a' 'a' 97
В следующем примере проиллюстрировано приведение типов с помощью формата (Имя_типа) Выражение :
print (float) i
print ((struct qq *) void_pointer)->first_element
Приведение типов в программе dbx выполняется по правилам языка C со следующими ограничениями:
Команда whatis выдает описание идентификатора, который может быть уточнен именем блока.
Конструкция $$тег применяется для печати описаний тегов перечислимых типов данных, структур и объединений (или аналогичных объектов языка Pascal).
Тип выражения в команде assign должен совпадать с типом переменной, который вы присваиваете. Если типы не совпадают, будет выдано сообщение об ошибке. Вы можете изменить тип выражения с помощью операции переименования типа. Для отключения контроля типов укажите специальную переменную $unsafeassign программы dbx.
По умолчанию программа dbx выполняет преобразование символов к нужному регистру в соответствии с текущим языком. Если текущий язык - C, C++ или не определен, то регистр символов не изменяется. Если текущий язык - FORTRAN или Pascal, то символы переводятся в нижний регистр. Текущий язык остается неопределенным, если программа находится в разделе кода, который не компилировался с флагом debug. Изменить настройку, установленную по умолчанию, можно с помощью команды case.
Команда case без аргументов показывает текущий регистр.
Компиляторы FORTRAN и Pascal преобразуют все символы программы в нижний регистр; компилятор C - нет.
С помощью команды set можно задать специальные переменные программы
dbx, которые изменяют формат вывода команды print:
Для получения результатов отладки в нужном вам формате установите необходимые переменные программы отладки. Например:
(dbx) whatis x; whatis i; whatis s int x; char i; char *s; (dbx) print x, i, s 375 'c' "hello" (dbx) set $hexstrings; set $hexints; set $hexchars (dbx) print x, i, s 0x177 0x63 0x3fffe460 (dbx) unset $hexchars; set $octints (dbx) print x, i 0567 'c' (dbx) whatis p struct info p; (dbx) whatis struct info struct info { int x; double position[3]; unsigned char c; struct vector force; }; (dbx) whatis struct vector struct vector { int a; int b; int c; }; (dbx) print p (x = 4, position = (1.3262493258532527e-315, 0.0, 0.0), c = '\0', force = (a = 0, b = 9, c = 1)) (dbx) set $pretty="on" (dbx) print p { x = 4 position[0] = 1.3262493258532527e-315 position[1] = 0.0 position[2] = 0.0 c = '\0' force = { a = 0 b = 9 c = 1 } } (dbx) set $pretty="verbose" (dbx) print p x = 4 position[0] = 1.3262493258532527e-315 position[1] = 0.0 position[2] = 0.0 c = '\0' force.a = 0 force.b = 9 force.c = 1
Программа символьной отладки dbx - Обзор
Работа с программой отладки dbx
Просмотр и редактирование исходного файла с помощью программы отладки dbx
Применение dbx для отладки на машинном уровне