mozilla rr
, GDB tersine hata ayıklamaya daha sağlam bir alternatiftir
https://github.com/mozilla/rr
GDB'nin yerleşik kaydı ve yeniden oynatması ciddi sınırlamalara sahiptir, örneğin AVX talimatları için destek yoktur: gdb ters hata ayıklama, "İşlem kaydı adreste 0xf0d talimatını desteklemiyor" ile başarısız olur
Rr'nin avantajları:
- şu anda çok daha güvenilir. Birkaç karmaşık yazılımın nispeten uzun sürelerini test ettim.
- ayrıca gdbserver protokolüne sahip bir GDB arayüzü sunar, bu da onu harika bir yedek haline getirir
- çoğu program için küçük bir performans düşüşü, ölçümler yapmadan bunu kendim fark etmedim
- oluşturulan izler diskte küçüktür çünkü yalnızca çok az deterministik olmayan olay kaydedilir, şimdiye kadar boyutları hakkında endişelenmek zorunda kalmadım
rr bunu, önce programı bir iş parçacığı anahtarı gibi deterministik olmayan her olayda olanları kaydedecek şekilde çalıştırarak başarır.
Daha sonra ikinci tekrar çalıştırma sırasında, orijinal deterministik olmayan çalışmada tam olarak ne olduğunu ancak ileriye veya geriye doğru belirleyici bir şekilde yeniden yapılandırmak için şaşırtıcı derecede küçük olan bu izleme dosyasını kullanır.
rr, ilk olarak Mozilla tarafından, ertesi gün gece testlerinde ortaya çıkan zamanlama hatalarını yeniden üretmelerine yardımcı olmak için geliştirildi. Ancak ters hata ayıklama yönü, yalnızca çalıştırma içinde saatler süren bir hataya sahip olduğunuzda da önemlidir, çünkü önceki durumun sonraki başarısızlığa yol açtığını incelemek için genellikle geri adım atmak istersiniz.
Aşağıdaki örnek bazı özellikleri, özellikle sergiliyor reverse-next
, reverse-step
ve reverse-continue
komutları.
Ubuntu 18.04'e yükleyin:
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
Test programı:
#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;
}
derleyin ve çalıştırın:
gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay
Artık bir GDB oturumunun içinde kaldınız ve hata ayıklamayı düzgün bir şekilde tersine çevirebilirsiniz:
(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;
Karmaşık yazılımlarda hata ayıklarken, muhtemelen bir çökme noktasına kadar koşacak ve ardından derin bir çerçevenin içine düşeceksiniz. Bu durumda, bunu reverse-next
daha yüksek karelerde için unutmayın, önce şunları yapmalısınız:
reverse-finish
o çerçeveye kadar, sadece her zamanki gibi yapmak up
yeterli değil.
Bence rr'nin en ciddi sınırlamaları:
UndoDB, rr: https ://undo.io'ya ticari bir alternatiftir. Her ikisi de izleme / tekrar oynatma tabanlıdır, ancak özellikler ve performans açısından nasıl karşılaştırıldıklarından emin değilim.