Можно ли "прыгать" / "пропустить" в отладчике GDB?

Я новичок в 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

Чтобы возобновить исполнение по новому адресу, используйте jump (короткая форма: j):

jump LINENUM
jump *ADDRESS

Руководство GDB предлагает использовать tbreak (временную точку останова) перед прыжком.

Белье может быть любым выражением linespec, например +1 для следующей строки.

См. @gospes answer по соответствующему вопросу для удобного макроса skip, который делает именно это.


Использование jump только "безопасно" в неуправляемом коде (-O0), и даже тогда только внутри текущей функции. Он только изменяет счетчик программ; он не меняет никаких других регистров или памяти.

Только gcc -O0 компилирует каждый оператор источника (или строку?) в отдельный блок инструкций, который загружает значения переменных из памяти и сохраняет результаты. Это позволяет изменять значения переменных с помощью отладчика в любой точке останова и делает jump между строками в машинных кодах работать как прыжок между строками в источнике C.

Это часть того, почему -O0 делает такой медленный код: компилятор не только не тратит время на оптимизацию, он должен делать медленный код, который разливает/перезагружает все после каждого утверждения для поддержки асинхронной модификации переменных и даже программ -counter. (Задержка хранения/перезагрузки составляет около 5 циклов на типичном x86, поэтому 1 цикл add занимает 6 циклов в строках -O0).

Руководство gcc предлагает использовать -Og для обычного цикла редактирования-компиляции-отладки, но даже этот уровень освещенности будет разорван jump и асинхронная модификация переменных. Если вы не хотите делать это во время отладки, это хороший выбор, особенно для проектов, где -O0 работает так медленно, что это проблема.


Чтобы установить программный счетчик/указатель инструкции на новый адрес без возобновления, вы также можете использовать это:

set $pc = 0x4005a5

Копировать/вставить адреса из окна разборки (layout asm/layout reg).

Это эквивалентно tbreak + jump, но вы не можете использовать номера строк, только адреса инструкций. (И вы не получите предупреждение + запрос подтверждения для перехода за пределы текущей функции).

Тогда вы можете stepi оттуда. $pc - это общее имя gdb для любого регистра, который действительно вызывается в целевой архитектуре. например RIP в x86-64. (См. Также нижнюю часть wiki для советов по отладке asm для gdb.)