Chromium Chronicle nr 13: debugowanie w czasie i podróży przy użyciu RR

Odcinek 13: Christian Biesinger w Madison, Wisconsin (marzec 2020 r.)
Poprzednie odcinki

Czy powtarzasz ten sam test w debugerze, próbując się dowiedzieć, dlaczego kod znalazł się w nieprawidłowym stanie? Mamy dla Ciebie narzędzie. Łatwa instalacja i konfiguracja. Zapisuje ślad wykonania, dzięki czemu gdb otrzymuje nowe magiczne moce. Krok wstecz, wstecz, sprawdź, gdzie zmienne zmieniły swoje wartości lub kiedy funkcja została ostatnio wywołana w obiekcie (z użyciem warunkowych punktów przerwania).

W Linuksie możesz użyć rr. Zainstaluj za pomocą programu sudo apt-get install rr lub strony https://rr-project.org/.

Ta opcja nie jest oficjalnie obsługiwana, ale bardzo przydatna. Działanie rr polega na zarejestrowaniu logu czasu, a potem odtworzeniu go ponownie.

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

Wygodnie adresy czasu i wskaźnika pozostają takie same przy każdym odtwarzaniu tego samego logu czasu. Śledzenie można przenieść za pomocą rr pack, co pozwala skopiować je na inny komputer i ponownie na nim odtworzyć lub odtworzyć nawet po ponownym skompilowaniu. Uruchom program jako continue. Możesz używać wszystkich zwykłych poleceń GDB -b, next, watch itp. Możesz też używać funkcji odwrotnie-następnej (rn), odwrotnego kroku (rc), odwrotnego kroku (rs) lub odwrotnego działania.

Nadal respektują one ustawione przez Ciebie punkty przerwania. Na przykład:

(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*> (

W tym przykładzie dla uproszczenia użyto funkcji --single-process, ale nie jest to konieczne. Funkcja RR może śledzić wiele procesów. Po zakończeniu nagrywania możesz wyświetlić listę za pomocą polecenia rr ps i wybrać jedną do ponownego odtworzenia w usłudze rr replay -f PID.

RR może być przydatny na wiele sposobów. Możesz użyć innych poleceń, np. sprawdzić, pod którym numerem wydarzenia się znajdujesz, lub rr replay -M dodać w każdym wierszu adnotację stdout z identyfikatorem procesu i numerem zdarzenia. Więcej informacji znajdziesz na stronie i w dokumentacji RRSO.