mozilla rr
- более надежная альтернатива обратной отладке GDB
https://github.com/mozilla/rr
Встроенная запись и воспроизведение GDB имеет серьезные ограничения, например, отсутствие поддержки инструкций AVX: обратная отладка gdb завершается неудачно с "Запись процесса не поддерживает инструкцию 0xf0d по адресу"
Плюсы р-р:
- намного надежнее в настоящее время. Я тестировал его на относительно длительных прогонах нескольких сложных программ.
- также предлагает интерфейс GDB с протоколом gdbserver, что делает его отличной заменой
- небольшое падение производительности для большинства программ, сам не заметил без замеров
- сгенерированные трассировки имеют небольшой размер на диске, потому что записывается очень мало недетерминированных событий, мне никогда не приходилось беспокоиться об их размере до сих пор
rr достигает этого, сначала запуская программу таким образом, чтобы записывать, что произошло при каждом недетерминированном событии, таком как переключение потока.
Затем во время второго прогона воспроизведения он использует этот файл трассировки, который на удивление мал, для точного восстановления того, что произошло в исходном недетерминированном прогоне, но детерминированным образом, в прямом или обратном направлении.
rr был первоначально разработан Mozilla, чтобы помочь им воспроизвести ошибки синхронизации, которые обнаружились во время их ночного тестирования на следующий день. Но аспект обратной отладки также важен, когда у вас есть ошибка, которая возникает только в течение нескольких часов после выполнения, поскольку вам часто нужно отступить, чтобы проверить, какое предыдущее состояние привело к последующему сбою.
Следующий пример демонстрирует некоторые из его особенностей, в частности reverse-next
, reverse-step
и reverse-continue
команду.
Установите на Ubuntu 18.04:
sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
sudo cpupower frequency-set -g performance
# Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Программа испытаний:
#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;
При отладке сложного программного обеспечения вы, скорее всего, дойдете до точки сбоя, а затем попадете в глубокий фрейм. В этом случае не забудьте, что для reverse-next
более высоких кадров вы должны сначала:
reverse-finish
до этого кадра просто делать обычные up
вещи недостаточно.
На мой взгляд, наиболее серьезные ограничения rr:
UndoDB - коммерческая альтернатива rr: https://undo.io. Оба они основаны на трассировке / воспроизведении, но я не уверен, как они сравниваются с точки зрения функций и производительности.