De Chromium Chronicle #13: foutopsporing in tijdreizen met RR

Aflevering 13: door Christian Biesinger in Madison, WI (maart 2020)
Vorige afleveringen

Merk je dat je dezelfde test keer op keer uitvoert in de debugger, in een poging erachter te komen hoe de code in een slechte staat terecht is gekomen? Wij hebben een hulpmiddel voor u! Het is eenvoudig te installeren en in te stellen, het registreert een uitvoeringsspoor en dat geeft magische nieuwe krachten aan gdb . Ga achteruit, ren achteruit , kijk waar variabelen hun waarde hebben gewijzigd of wanneer een functie voor het laatst op een object is aangeroepen (met behulp van voorwaardelijke breekpunten).

Op Linux kun je rr gebruiken . Installeer met sudo apt-get install rr of vanaf https://rr-project.org/ .

Dit wordt niet officieel ondersteund, maar is wel erg handig. De manier waarop rr werkt is dat u eerst een spoor opneemt en het vervolgens opnieuw afspeelt .

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

Handig genoeg blijven de timing- en pointeradressen hetzelfde elke keer dat u hetzelfde spoor opnieuw afspeelt. Traces kunnen draagbaar worden gemaakt met behulp van rr pack , zodat u ze naar een andere machine kunt kopiëren en daar opnieuw kunt afspelen, of zelfs na opnieuw compileren. Voer uw programma uit met continue . U kunt alle reguliere GDB-opdrachten gebruiken -b , next , watch , etc. U kunt echter ook reverse-next ( rn ), reverse-cont ( rc ), reverse-step ( rs ), reverse-fin gebruiken.

Deze respecteren nog steeds alle breekpunten die u heeft ingesteld. Bijvoorbeeld:

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

In dit voorbeeld heb ik --single-process gebruikt voor de eenvoud, maar dat is niet nodig. RR kan meerdere processen traceren ; na het opnemen kun je een lijst bekijken met rr ps en er een kiezen om af te spelen met rr replay -f PID .

Er zijn veel manieren waarop RR nuttig kan zijn. Er zijn nog andere opdrachten die u kunt gebruiken , zoals wanneer u wilt weten op welk gebeurtenisnummer u zich bevindt, of rr replay -M om stdout te annoteren met een proces-ID en gebeurtenisnummer voor elke regel. Zie de RR-website en documentatie voor meer details.