Чтобы возобновить выполнение по новому адресу, используйте jump
(краткая форма: j
):
jump LINENUM
jump *ADDRESS
В руководстве по GDB предлагается использовать tbreak
(временная точка останова)) перед прыжком.
белье может быть любым linespec
выражением, например +1
для следующей строки.
См. @ gospes's answer по связанному вопросу для удобного skip
макроса, который именно это и делает.
Использование jump
только "безопасно" в неоптимизированном коде (-O0
) и даже тогда только в пределах текущей функции.Он только изменяет счетчик программы;он не изменяет никакие другие регистры или память.
Только gcc -O0
компилирует каждый исходный оператор (или строку?) в независимый блок инструкций, который загружает значения переменных из памяти и сохраняет результаты.Это позволяет вам изменять значения переменных с помощью отладчика в любой точке останова, а jump
между строками в машинном коде работает как переход между строками в исходном коде C.
Это часть того, почему -O0
делаеттакой медленный код: компилятор не только не тратит время на оптимизацию, он также требует создания медленного кода, который проливает / перезагружает все после каждого оператора для поддержки асинхронного изменения переменных и даже счетчика программы.(Задержка сохранения / перезагрузки составляет около 5 циклов на типичном x86, поэтому 1 цикл add
занимает 6 циклов в сборках -O0
.)
Руководство gcc предлагает использовать -Og
для обычного цикла edit-compile-debug, но даже этот легкий уровень оптимизации нарушит jump
и асинхронную модификацию переменных.Если вы не хотите делать это во время отладки, это хороший выбор, особенно для проектов, где -O0
работает так медленно, что это проблема.
Чтобы установить счетчик программы /указатель на новый адрес без возобновления , вы также можете использовать это:
set $pc = 0x4005a5
Копировать / вставить адреса из окна разборки (layout asm
/ layout reg
).
Это эквивалентно tbreak
+ jump
, но вы не можете использовать номера строк, только адреса команд.(И вы не получите предупреждение + запрос подтверждения для перехода за пределы текущей функции).
Тогда вы можете stepi
оттуда.$pc
- это общее имя GDB для того, что регистр действительно называется в целевой архитектуре.например, RIP в x86-64.(См. Также нижнюю часть вики x86 для советов по отладке asm для GDB.)