Chromium Chronicle #13: Gỡ lỗi du hành thời gian bằng RR

Tập 13: Tác giả: Christian Biesinger ở Madison, WI (Tháng 3 năm 2020)
Các tập trước

Bạn có phải chạy cùng một bài kiểm thử nhiều lần trong trình gỡ lỗi, cố gắng tìm hiểu xem mã ở trạng thái xấu như thế nào không? Chúng tôi có một công cụ dành cho bạn! Dễ dàng cài đặt và thiết lập, tính năng này sẽ ghi lại dấu vết thực thi, đồng thời cung cấp quyền lực mới kỳ diệu cho gdb. Lùi, chạy lùi, xem vị trí các biến thay đổi giá trị hoặc thời điểm một hàm được gọi gần đây nhất trên một đối tượng (sử dụng các điểm ngắt có điều kiện).

Trên Linux, bạn có thể dùng rr. Cài đặt bằng sudo apt-get install rr hoặc trên https://rr-project.org/.

Tính năng này không được hỗ trợ chính thức nhưng rất hữu ích. Cách hoạt động của rrtrước tiên, bạn ghi lại một dấu vết, sau đó phát lại dấu vết đó.

rr record .../content_shell --no-sandbox  --disable-hang-monitor --single-process
# record the trace. --single-process is optional, see below. The other flags are required.
rr replay # This will replay the last trace
(gdb)       # rr uses GDB to let you replay traces

Điểm thuận tiện là thời gian và địa chỉ con trỏ vẫn giữ nguyên mỗi khi bạn phát lại cùng một dấu vết. Bạn có thể di chuyển dấu vết bằng cách sử dụng rr pack để có thể sao chép các dấu vết đó vào một máy khác và phát lại ở đó hoặc phát lại ngay cả sau khi biên dịch lại. Chạy chương trình bằng continue. Bạn có thể sử dụng tất cả các lệnh GDB thông thường -b, next, watch, v.v. Tuy nhiên, bạn cũng có thể sử dụng đảo tiếp theo (rn), đảo ngược tiếp tục (rc), đảo ngược (rs), đảo ngược.

Các mã này vẫn tuân theo mọi điểm ngắt mà bạn đã đặt. Ví dụ:

(gdb) c  # Execute to the end
(gdb) break blink::LayoutFlexibleBox::UpdateLayout
(gdb) rc # Run back to the last layout call
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) # Inspect anything you want here. To find the previous Layout call on this object:
(gdb) cond 1 this == 0x121672224010
(gdb) rc
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) watch -l style_.ptr_ # Or find the last time the style_ was changed
(gdb) rc
Thread 5 hit Hardware watchpoint 2: -location style_.ptr_

Old value = (const blink::ComputedStyle *) 0x1631ad3dbb0
New value = (const blink::ComputedStyle *) 0x0
0x00007f68cabcf78e in std::__Cr::swap<blink::ComputedStyle const*> (

Trong ví dụ này, tôi dùng --single-process để đơn giản, nhưng điều đó là không cần thiết. RR có thể theo dõi nhiều quá trình; sau khi ghi, bạn có thể xem danh sách bằng rr ps và chọn một danh sách để phát lại bằng rr replay -f PID.

Có rất nhiều cách để lập chỉ mục RR. Bạn có thể sử dụng các lệnh khác mà bạn có thể sử dụng, chẳng hạn như thời điểm tìm hiểu số sự kiện bạn đang ở hoặc rr replay -M để chú thích stdout bằng mã quy trình và số sự kiện cho mỗi dòng. Hãy xem trang web và tài liệu về Bản ghi âm (RR) để biết thêm thông tin chi tiết.