मोज़िला rr
जीडीबी रिवर्स डिबगिंग का अधिक मजबूत विकल्प है
https://github.com/mozilla/rr
GDB के अंतर्निहित रिकॉर्ड और रिप्ले में गंभीर सीमाएँ हैं, उदाहरण के लिए AVX निर्देशों का कोई समर्थन नहीं: gdb रिवर्स डिबगिंग "प्रक्रिया रिकॉर्ड पते पर निर्देश 0xf0d का समर्थन नहीं करता है" के साथ विफल रहता है
Rr के अपसाइड:
- वर्तमान में बहुत अधिक विश्वसनीय। मैंने कई जटिल सॉफ़्टवेयरों के अपेक्षाकृत लंबे रन का परीक्षण किया है।
- gdbserver प्रोटोकॉल के साथ एक GDB इंटरफ़ेस भी प्रदान करता है, जो इसे एक बेहतरीन प्रतिस्थापन बनाता है
- अधिकांश कार्यक्रमों के लिए छोटे प्रदर्शन ड्रॉप, मैंने खुद को माप किए बिना इस पर ध्यान नहीं दिया
- उत्पन्न निशान डिस्क पर छोटे होते हैं क्योंकि केवल कुछ ही गैर-नियतात्मक घटनाएं दर्ज की जाती हैं, मुझे अब तक उनके आकार के बारे में चिंता करने की ज़रूरत नहीं है
rr इसे पहली बार प्रोग्राम को इस तरह से चलाकर प्राप्त करता है जो रिकॉर्ड करता है कि थ्रेड स्विच जैसे हर एक गैर-निर्धारक घटना पर क्या हुआ।
फिर दूसरे रिप्ले रन के दौरान, यह उस ट्रेस फ़ाइल का उपयोग करता है, जो आश्चर्यजनक रूप से छोटा है, मूल गैर-नियतात्मक रन पर वास्तव में क्या हुआ, यह निर्धारित करने के लिए, लेकिन नियतात्मक तरीके से, आगे या पीछे।
rr को मूल रूप से मोज़िला द्वारा विकसित किया गया था ताकि उन्हें टाइमिंग बग्स को पुन: उत्पन्न करने में मदद मिल सके जो कि अगले दिन उनके रात के परीक्षण में दिखाई दिए थे। लेकिन रिवर्स डिबगिंग पहलू तब भी मौलिक होता है जब आपके पास एक बग होता है जो केवल निष्पादन के घंटे के भीतर होता है, क्योंकि आप अक्सर यह जांचना चाहते हैं कि बाद की स्थिति के कारण पिछली स्थिति क्या थी।
निम्न उदाहरण इसकी कुछ विशेषताओं को दर्शाता है, विशेष रूप से 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 दोनों ट्रेस / रीप्ले आधारित हैं, लेकिन मुझे यकीन नहीं है कि वे सुविधाओं और प्रदर्शन के मामले में कैसे तुलना करते हैं।