mozilla rr
là một giải pháp thay thế mạnh mẽ hơn cho gỡ lỗi ngược GDB
https://github.com/mozilla/rr
Bản ghi và phát lại tích hợp của GDB có những hạn chế nghiêm trọng, chẳng hạn như không hỗ trợ hướng dẫn AVX: gỡ lỗi ngược gdb không thành công với "Bản ghi quy trình không hỗ trợ lệnh 0xf0d tại địa chỉ"
Mặt trước của rr:
- đáng tin cậy hơn nhiều hiện tại. Tôi đã thử nghiệm nó chạy tương đối lâu một số phần mềm phức tạp.
- cũng cung cấp giao diện GDB với giao thức gdbserver, làm cho nó trở thành một sự thay thế tuyệt vời
- giảm hiệu suất nhỏ đối với hầu hết các chương trình, bản thân tôi đã không nhận thấy điều đó nếu không thực hiện các phép đo
- các dấu vết được tạo nhỏ trên đĩa vì chỉ có rất ít sự kiện không xác định được ghi lại, tôi chưa bao giờ phải lo lắng về kích thước của chúng cho đến nay
rr đạt được điều này bằng cách đầu tiên chạy chương trình theo cách ghi lại những gì đã xảy ra trên mọi sự kiện không xác định, chẳng hạn như chuyển đổi luồng.
Sau đó, trong lần chạy phát lại thứ hai, nó sử dụng tệp theo dõi đó, nhỏ đáng ngạc nhiên, để tái tạo lại chính xác những gì đã xảy ra trên lần chạy không xác định ban đầu nhưng theo cách xác định, tiến hoặc lùi.
rr ban đầu được phát triển bởi Mozilla để giúp họ tái tạo các lỗi thời gian xuất hiện trong bài kiểm tra hàng đêm của họ vào ngày hôm sau. Nhưng khía cạnh gỡ lỗi ngược cũng là cơ bản khi bạn gặp lỗi chỉ xảy ra hàng giờ trong quá trình thực thi, vì bạn thường muốn lùi lại để kiểm tra trạng thái trước đó dẫn đến lỗi sau này.
Ví dụ sau đây giới thiệu một số tính năng của nó, đặc biệt là reverse-next
, reverse-step
và reverse-continue
lệnh.
Cài đặt trên 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
Chương trình kiểm tra:
#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;
}
biên dịch và chạy:
gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay
Bây giờ bạn ở bên trong phiên GDB và bạn có thể đảo ngược gỡ lỗi đúng cách:
(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;
Khi gỡ lỗi phần mềm phức tạp, bạn có thể sẽ gặp sự cố và sau đó rơi vào một khung hình sâu. Trong trường hợp đó, đừng quên rằng đối reverse-next
với các khung hình cao hơn, trước tiên bạn phải:
reverse-finish
lên đến khung đó, chỉ làm thông thường up
là không đủ.
Những hạn chế nghiêm trọng nhất của rr theo ý kiến của tôi là:
UndoDB là một giải pháp thay thế thương mại cho rr: https://undo.io Cả hai đều dựa trên dấu vết / phát lại, nhưng tôi không chắc chúng so sánh như thế nào về tính năng và hiệu suất.