Можно ли "прыгать"/"пропускать" в отладчике GDB?
Можно ли перейти к некоторому местоположению / адресу в коде / исполняемом файле во время отладки в GDB?
Допустим, у меня есть что-то похожее на следующее
int main()
{
caller_f1() {
f1(); // breakpoint
f2() } // want to skip f2() and jump
caller_f2() { // jump to this this location ??
f1();
f2(); }
}
2 ответа
Кажется, есть команда перехода, которая именно то, что вы ищете:
http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html
Обновленная ссылка: http://web.archive.org/web/20140101193811/http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html
Чтобы возобновить выполнение по новому адресу, используйте jump
(Краткая форма: j
):
jump LINENUM
jump *ADDRESS
Руководство GDB предлагает использовать tbreak
(временная точка останова) перед прыжком.
Белье может быть любым linespec
выражение, как +1
для следующей строки.
Смотрите ответ @gospes на соответствующий вопрос для удобной 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.)