Отладка с помощью GDB - 11. Изменение выполнения
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]11. Изменение выполнения
Если вы думаете, что нашли ошибку в своей программе, вы можете захотеть выяснить наверняка, приведет ли исправление кажущейся ошибки к правильным результатам в остальной части программы. Вы можете получить ответ экспериментируя, используя средства GDB для изменения выполнения программы.
Например, вы можете сохранить новые значения в переменных или ячейках памяти, подать своей программе сигнал, перезапустить ее с другого адреса или даже преждевременно вернуться из функции.
11.1 Присваивание значений пеpеменным
Для изменения значения переменной, вычислите выражение присваивания. См. раздел 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.
11.2 Продолжение исполнения с другого адреса
Обычно, когда вы продолжаете выполнение программы, вы делаете это
с того места, где она остановилась, командой continue
. Вместо
этого, вы можете продолжить выполнение с любого выбранного адреса
при помощи следующих команд:
jump указ-стр
-
Возобновить выполнение со строки указ-стр. Если там есть точка
останова, выполнение немедленно прекращается. См. раздел 7.1 Вывод строк исходного текста, для описания различных форм указ-стр.
Использование команды
tbreak
вместе сjump
является обычной практикой. См. раздел 5.1.1 Установка точек останова. Командаjump
не изменяет ни текущий кадр стека, ни указатель стека, ни содержимое каких-либо ячеек памяти или регистров, кроме счетчика программы. Если строка указ-стр находится вне выполняющейся в настоящее время функции, результаты могут быть странными, если эти функции используют аргументы или локальные переменные разных типов. По этой причине, командаjump
запрашивает подтверждение, если указанная строка не находится в функции, выполняющейся в настоящее время. Однако, даже странные результаты предсказуемы, если вы хорошо знакомы с машинным кодом вашей программы. jump *адрес
- Возобновить выполнение с инструкции, находящейся по адресу адрес.
На многих системах, вы можете достичь такого же результата, как и с командой
jump
, сохранением нового значения в регистр $pc
. Отличие в
заключается том, что это не начинает выполнение вашей программы, а лишь
изменяет адрес, с которого будет выполняться программа,
когда вы продолжите выполнение. Например,
set $pc = 0x485
выполняет следующую команду continue
или команду пошагового
выполнения с адреса 0x485
, а не с того адреса, где ваша программа
остановилась. См. раздел 5.2 Продолжение и выполнение по шагам.
Наиболее общий случай использования команды jump
состоит в
возврате к выполнению части программы, возможно с большим количеством
установленных точек останова, которая уже выполнилась, для того чтобы
исследовать выполнение более детально.
11.3 Подача сигнала вашей программе
signal сигнал
-
Возобновить выполнение с места остановки вашей программы, но немедленно
подать ей сигнал сигнал. Сигнал может быть именем или номером
сигнала. Например, во многих системах
signal 2
иsignal SIGINT
---два способа подать сигнал прерывания. Наоборот, если сигнал является нулем, выполнение продолжается без подачи сигнала. Это полезно, если ваша программа остановилась из-за сигнала и в обычном случае увидит его при возобновлении выполнения командойcontinue
; `signal 0' продолжит выполнение без сигнала.signal
не повторяется, когда вы нажимаете RET второй раз после выполнения команды.
Вызов команды signal
отличается от вызова утилиты kill
из
оболочки. Подача сигнала посредством kill
заставляет
GDB решать, что делать с сигналом, в зависимости от таблиц
обработки сигналов (см. раздел 5.3 Сигналы). Команда signal
передает
сигнал непосредственно вашей программе.
11.4 Возврат из функции
return
return выражение
-
Вы можете отменить выполнение вызова функции с помощью команды
return
. Если вы задаете параметр выражение, его значение используется в качестве возвращаемого значения.
Когда вы используете return
, GDB уничтожает выбранный
кадр стека (и все кадры внутри него). Вы можете считать это
преждевременным возвратом из уничтоженного кадра. Если вы хотите
указать возвращаемое значение, задайте его в качестве аргумента к
return
.
Это выталкивает выбранный кадр стека (см. раздел 6.3 Выбор кадра) и все другие кадры внутри него, оставляя самым внутренним кадр, из которого произошел вызов. Этот кадр становится выбранным. Указанное значение сохраняется в регистрах, используемых для возвращаемых функцией значений.
Команда return
не возобновляет выполнение; она оставляет
программу остановленной в том состоянии, в котором бы она была сразу
после возврата из функции. Напротив, команда finish
(см. раздел 5.2 Продолжение и выполнение по шагам) возобновляет выполнение до естественного возврата из
выбранного кадра стека.
11.5 Вызов функций программы
call выраж
-
Вычислить выражение выраж без отображения пустых (
void
) возвращенных значений.
Вы можете использовать этот вариант команды print
, если хотите
выполнить функцию из вашей программы, не засоряя вывод пустыми возвращенными
значениями. Если результат не пустой, он выводится и
сохраняется в истории значений.
Для A29K, устанавливаемая пользователем переменная
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
- Показать, открыты исполняемые файлы и файлы дампов памяти для записи или нет.
[Содержание] [Назад] [Пред] [Вверх] [След] [Вперед]