Chromium Chronicle #13: depuração de viagens no tempo com RR

Episódio 13:por Christian Biesinger em Madison, WI (março de 2020)
Episódios anteriores

Você executa o mesmo teste várias vezes no depurador, tentando descobrir como o código está em mau estado? Temos uma ferramenta para você. Fácil de instalar e configurar, ele registra um rastro de execução e dá novos poderes a gdb. Retroceder, executar para trás, veja onde as variáveis mudaram de valor ou quando uma função foi chamada pela última vez em um objeto (usando pontos de interrupção condicionais).

No Linux, você pode usar rr. Instale usando sudo apt-get install rr ou em https://rr-project.org/.

Isso não é oficialmente compatível, mas é muito útil. A forma como rr funciona é que você primeiro grava um rastro e depois o reproduz de novo.

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

A marcação de tempo e os endereços de ponteiro permanecem os mesmos toda vez que você repete o mesmo rastro. Os rastros podem ser tornados portáteis usando rr pack para que você possa copiá-los em outra máquina e reproduzi-los nela ou reproduzi-los mesmo após a recompilação. Execute o programa usando continue. Você pode usar todos os comandos normais do GDB -b, next, watch etc. No entanto, também é possível usar reverse-next (rn), reverse-cont (rc), reverse-step (rs) reverse-fin.

Eles ainda respeitam todos os pontos de interrupção definidos. Exemplo:

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

Neste exemplo, usei --single-process para simplificar, mas isso não é necessário. A RR pode rastrear vários processos. Após a gravação, você pode ver uma lista usando rr ps e escolher um para reproduzir com rr replay -f PID.

A RR pode ser útil de várias maneiras. Há outros comandos que podem ser usados, como quando descobrir em que número de evento você está ou rr replay -M para anotar stdout com um ID de processo e um número de evento para cada linha. Consulte o site e a documentação do RR para saber mais.