Как перейти к предыдущей строке в GDB?
Возможно ли в gdb перейти к строке перед текущей исполняемой строкой.
например:
void my_fun( somePtrType** arr,int start,int end)
{
// arr is an array of pointers to somePtrType
//line a
... some assignments
swap(&arr[ind1] , &arr[ind2] ) ;
//line b (current line )
}
Сейчас я на линии b и могу проверить значения arr
, но я хочу вернуться к строке a и изучить содержимое arr
в это время.
Я думаю, что это может быть невозможно, потому что отладчик может запускать код в замедленном режиме, но не может выполнить его заново.
Более подробная информация..
Ответы
Ответ 1
Да! С новой версией 7.0 gdb вы можете сделать именно это!
Команда будет "reverse-step
" или "reverse-next
".
Вы можете получить gdb-7.0 из ftp.gnu.org:/pub/gnu/gdb
Если вы столкнулись с ошибкой: Target child does not support this command.
, попробуйте добавить target record
в начале выполнения, после запуска run
.
Изменить: поскольку GDB 7.6 target record
устарел, используйте target record-full
вместо этого.
Ответ 2
Да, это возможно и прямо сейчас, с реальным оборудованием (т.е. не только с виртуальной машиной).
GDB-7.0 поддерживает обратную отладку с такими командами, как обратное и обратное-продолжение, на собственных машинах Linux x86.
Здесь есть учебник: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
Ответ 3
Короткий ответ: №
Для обходного пути ниже.
Хотя на строке b невозможно определить значение в строке a, можно зарегистрировать значение arr в и b и других местах только с ударом только одной точки останова.
- Используйте команду display (display variable_name, где variable_name должно быть заменено на arr, * arr, ** arr в зависимости от того, что вы ищете), чтобы при достижении любой точки останова содержимое переменной_имя будет сбрасывается на экран. Обратите внимание, что вы можете добавить в список отображения, когда имя variabe_name находится в области видимости, поэтому вам может потребоваться дождаться вашей первой точки останова.
- Создайте точки останова в разных местах кода, где вам интересно записать значение переменной_имя. Одна такая точка останова была бы на линии a.
- Для каждой точки останова используйте команду (команда breakpoint_number) и сообщите своей точке останова, чтобы не остановить выполнение программы. Команда, которую вам нужно использовать, продолжается и заканчивается. См. Пример ниже.
(gdb) команда 1
Введите команды, когда точка останова 1 попадает, по одному на строку. Конец с строкой, говорящей только "конец".
продолжить
конец
- Поместите точку останова на строку b.
Теперь, когда будут удалены все остальные точки останова, значение arr будет сброшено на экран, но точка останова не будет ждать взаимодействия с пользователем и будет автоматически продолжена. Когда вы нажмете точку останова в строке b, вы увидите последние значения arr, которые будут записаны в gdb.
В зависимости от ситуации вы также можете сбрасывать (и отображать) много полезной информации. Например, вы также можете сбросить счетчик циклов (скажем, i), если вышеуказанная функция вызывается 10000 раз в цикле. Это действительно зависит от того, чего вы пытаетесь достичь.
Ответ 4
Mozilla RR
https://github.com/mozilla/rr
Встроенная запись и воспроизведение в GDB имеют серьезные ограничения, например, нет поддержки инструкций AVX: обратная отладка gdb завершается неудачно с "Запись процесса не поддерживает инструкцию 0xf0d по адресу"
Вверх р-р:
- гораздо надежнее в настоящее время
- также предлагает интерфейс GDB с протоколом gdbserver, что делает его отличной заменой
- небольшое падение производительности для многих программ
В следующем примере демонстрируются некоторые из его функций, в частности, команды reverse-next
, reverse-step
и reverse-continue
.
Установите в Ubuntu 16.04:
sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
sudo cpupower frequency-set -g performance
Но также подумайте о компиляции из исходного кода, чтобы получить последние обновления, это было не сложно.
reverse.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int f() {
int i;
i = 0;
i = 1;
i = 2;
return i;
}
int main(void) {
int i;
i = 0;
i = 1;
i = 2;
/* Local call. */
f();
printf("i = %d\n", i);
/* Is randomness completely removed?
* Recently fixed: https://github.com/mozilla/rr/issues/2088 */
i = time(NULL);
printf("time(NULL) = %d\n", i);
return EXIT_SUCCESS;
}
скомпилируйте и запустите:
gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay
Теперь вы остались внутри сеанса GDB, и вы можете правильно отменить отладку:
(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
(rr) next
17 i = 1;
(rr) print i
$1 = 0
(rr) next
18 i = 2;
(rr) print i
$2 = 1
(rr) reverse-next
17 i = 1;
(rr) print i
$3 = 0
(rr) next
18 i = 2;
(rr) print i
$4 = 1
(rr) next
21 f();
(rr) step
f () at a.c:7
7 i = 0;
(rr) reverse-step
main () at a.c:21
21 f();
(rr) next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) reverse-next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$5 = 1509245372
(rr) reverse-next
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$6 = 1509245372
(rr) reverse-continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
Ответ 5
в соответствии с http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 и "если целевая среда поддерживает его", да.
Ответ 6
Если ваша программа коротка, обычным трюком является
- Поместите новую точку останова на предыдущую строку
- fire
r
, чтобы перезапустить debug
GDB было сделано для этого!
Ответ 7
Не gdb, но вы можете вернуться в историю легко с помощью отладчика, называемого qira. Вы можете использовать стрелки вверх и вниз, чтобы идти туда и обратно, а также подчеркивает, какие регистры изменились.
![введите описание изображения здесь]()
Ответ 8
Все хотят использовать Omniscient Debugger следующим образом: http://www.lambdacs.com/debugger/, но они (в зависимости от языка/машины) сложны сделать и иметь много бухгалтерии.
В настоящий момент на реальном оборудовании, а не на виртуальной машине, это почти невозможно сделать.
Ответ 9
Если ваш код установки для arr находится чуть выше "строки a" (очень часто используемый сценарий), вы можете сделать это следующим образом:
tbreak myfilename.c:123
(строка 123 - начало кода установки для arr), затем
jump 123
"tbreak" предотвращает продолжение gdb (возобновление) программы после прыжка.
то вы можете пройти через установочный код или просто установить точку останова в строке "a" и продолжить