Отладка с помощью GDB - 11. Изменение выполнения
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]
Если вы думаете, что нашли ошибку в своей программе, вы можете захотеть
выяснить наверняка, приведет ли исправление кажущейся ошибки к
правильным результатам в остальной части программы. Вы можете получить
ответ экспериментируя, используя средства GDB для изменения
выполнения программы.
Например, вы можете сохранить новые значения в переменных или
ячейках памяти, подать своей программе сигнал, перезапустить ее
с другого адреса или даже преждевременно вернуться из функции.
Для изменения значения переменной, вычислите выражение присваивания.
См. раздел 8.1 Выражения. Например,
print x=4
сохраняет значение 4 в переменной x и затем выводит значение данного
выражения (которое равно 4). См. раздел 9. Использование GDB с различными языками программирования, для получения большей инфоpмации
об операторах в поддерживаемых языках.
Если вы не хотите видеть значение присваивания, используйте команду
set вместо print . Команда set аналогична команде
print за исключением того, что значение выражения не выводится и не
заносится в историю значений (см. раздел 8.8 История значений). Выражение вычисляется только ради его действия.
Если начало строки параметров команды set выглядит идентично
подкоманде set , используйте вместо нее команду set
variable . Эта команда аналогична set , но не имеет подкоманд.
Например, если в вашей программе есть переменная width , то вы получите
ошибку, если попытаетесь установить новое значение просто с помощью
`set width=13', потому что GDB имеет команду
set width :
(gdb) whatis width
type = double
(gdb) p width
$4 = 13
(gdb) set width=47
Invalid syntax in expression.
Недопустимое выражение, это, конечно, `=47'. Для того чтобы
действительно установить переменную программы width , используйте
(gdb) set var width=47
Так как команда set имеет много подкоманд, которые могут
конфликтовать с именами переменных в программе, то хорошей практикой
является использование команды set variable вместо просто
set . Например, если ваша программа имеет переменную g , у
вас возникнут проблемы, если вы попытаетесь установить новое значение
с помощью `set g=4', потому что GDB имеет команду
set gnutarget , которая сокращается как set g :
(gdb) whatis g
type = double
(gdb) p g
$1 = 1
(gdb) set g=4
(gdb) p g
$2 = 1
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/smith/cc_progs/a.out
"/home/smith/cc_progs/a.out": can't open to read symbols: Invalid bfd target.
(gdb) show g
The current BFD target is "=4".
Переменная программы g не изменилась, и вы незаметно установили
gnutarget в неверное значение. Для установки значения переменной
g , используйте
(gdb) set var g=4
GDB допускает больше неявных преобразований в присваиваниях,
чем Си; вы можете свободно сохранить целое значение в
переменной-указателе и наоборот, преобразовать любую структуру к любой
другой, которая имеет ту же длину или короче.
Для сохранения значений в произвольных местах
памяти, используйте конструкцию `{...}' для создания
значения определенного типа по определенному адресу памяти
(см. раздел 8.1 Выражения). Например, {int}0x83040
ссылается на ячейку памяти 0x83040 как на целое (что
предполагает соответствующий размер и представление в памяти), и
set {int}0x83040 = 4
записывает в эту ячейку памяти значение 4.
Обычно, когда вы продолжаете выполнение программы, вы делаете это
с того места, где она остановилась, командой continue . Вместо
этого, вы можете продолжить выполнение с любого выбранного адреса
при помощи следующих команд:
jump указ-стр
-
Возобновить выполнение со строки указ-стр. Если там есть точка
останова, выполнение немедленно прекращается. См. раздел 7.1 Вывод строк исходного текста, для описания различных форм указ-стр.
Использование команды
tbreak вместе с jump является
обычной практикой. См. раздел 5.1.1 Установка точек останова.
Команда jump не изменяет ни текущий кадр стека, ни
указатель стека, ни содержимое каких-либо ячеек памяти или регистров, кроме
счетчика программы. Если строка указ-стр находится вне
выполняющейся в настоящее время функции,
результаты могут быть странными, если эти
функции используют аргументы или локальные переменные разных типов. По
этой причине, команда jump запрашивает подтверждение, если
указанная строка не находится в функции, выполняющейся в настоящее
время. Однако, даже странные результаты предсказуемы, если вы хорошо
знакомы с машинным кодом вашей программы.
jump *адрес
-
Возобновить выполнение с инструкции, находящейся по адресу адрес.
На многих системах, вы можете достичь такого же результата, как и с командой
jump , сохранением нового значения в регистр $pc . Отличие в
заключается том, что это не начинает выполнение вашей программы, а лишь
изменяет адрес, с которого будет выполняться программа,
когда вы продолжите выполнение. Например,
set $pc = 0x485
выполняет следующую команду continue или команду пошагового
выполнения с адреса 0x485 , а не с того адреса, где ваша программа
остановилась. См. раздел 5.2 Продолжение и выполнение по шагам.
Наиболее общий случай использования команды jump состоит в
возврате к выполнению части программы, возможно с большим количеством
установленных точек останова, которая уже выполнилась, для того чтобы
исследовать выполнение более детально.
signal сигнал
-
Возобновить выполнение с места остановки вашей программы, но немедленно
подать ей сигнал сигнал. Сигнал может быть именем или номером
сигнала. Например, во многих системах
signal 2 и signal
SIGINT ---два способа подать сигнал прерывания.
Наоборот, если сигнал является нулем, выполнение продолжается без
подачи сигнала. Это полезно, если ваша программа остановилась из-за
сигнала и в обычном случае увидит его при возобновлении выполнения командой
continue ; `signal 0' продолжит выполнение без сигнала.
signal не повторяется, когда вы нажимаете RET второй раз
после выполнения команды.
Вызов команды signal отличается от вызова утилиты kill из
оболочки. Подача сигнала посредством kill заставляет
GDB решать, что делать с сигналом, в зависимости от таблиц
обработки сигналов (см. раздел 5.3 Сигналы). Команда signal передает
сигнал непосредственно вашей программе.
return
-
return выражение
-
Вы можете отменить выполнение вызова функции с помощью команды
return .
Если вы задаете параметр выражение, его значение используется
в качестве возвращаемого значения.
Когда вы используете return , GDB уничтожает выбранный
кадр стека (и все кадры внутри него). Вы можете считать это
преждевременным возвратом из уничтоженного кадра. Если вы хотите
указать возвращаемое значение, задайте его в качестве аргумента к
return .
Это выталкивает выбранный кадр стека (см. раздел 6.3 Выбор кадра)
и все другие кадры внутри него, оставляя самым внутренним кадр, из
которого произошел вызов. Этот кадр становится выбранным. Указанное
значение сохраняется в регистрах, используемых для возвращаемых функцией
значений.
Команда return не возобновляет выполнение; она оставляет
программу остановленной в том состоянии, в котором бы она была сразу
после возврата из функции. Напротив, команда finish
(см. раздел 5.2 Продолжение и выполнение по шагам) возобновляет выполнение до естественного возврата из
выбранного кадра стека.
call выраж
-
Вычислить выражение выраж без отображения пустых (
void )
возвращенных значений.
Вы можете использовать этот вариант команды print , если хотите
выполнить функцию из вашей программы, не засоряя вывод пустыми возвращенными
значениями. Если результат не пустой, он выводится и
сохраняется в истории значений.
Для A29K, устанавливаемая пользователем переменная
call_scratch_address задает положение рабочей области, которая
будет использоваться, когда GDB вызывает функцию на целевой машине.
Это необходимо, так как обычный метод размещения рабочей области в стеке
не работает в системах с раздельными областями команд и данных.
По умолчанию, GDB открывает файл, содержащий исполняемый код вашей
программы (или файл дампа памяти), в режиме только для чтения. Это
предотвращает случайные изменения машинного кода; но это также предотвращает
и преднамеренное исправление двоичного файла вашей программы.
Если вы хотите иметь возможность исправлять двоичный код, вы можете
указать это явно с помощью команды set write . Например, вы
можете захотеть установить внутренние флаги отладки или даже сделать
аварийные исправления.
set write on
-
set write off
-
Если вы установите `set write on', GDB открывает исполняемые
файлы и файлы дампов памяти в режиме для чтения и записи; если вы
укажете `set write off' (устанавливается по умолчанию), GDB
открывает их в режиме только для чтения.
Если вы уже загрузили файл, то после установки
set write вам
необходимо загрузить его снова (используя команды exec-file или
core-file ), чтобы новые установки вступили в силу.
show write
-
Показать, открыты исполняемые файлы и файлы дампов памяти для
записи или нет.
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]
|