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 ficou em um estado defeituoso? Temos uma ferramenta para você! Ele é fácil de instalar e configurar, grava um rastro de execução e oferece novos poderes mágicos para gdb. Retroceder, recuar, ver para onde variáveis mudaram seu 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. Instalar usando sudo apt-get install rr ou em https://rr-project.org/ (link em inglês).

Não há suporte oficial, mas é muito útil. O rr funciona assim: grave primeiro um rastro e depois reproduza-o.

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

Convenientemente, os endereços de marcação de tempo e tempo permanecem os mesmos toda vez que você assiste o mesmo trace. Os rastros podem ser portáteis usando o rr pack para que você pode copiá-los para outra máquina e reproduzir novamente lá ou reproduzir mesmo depois recompilação. Execute o programa usando continue. Você pode usar todos os Os comandos -b, next, watch etc. do GDB, entre outros. No entanto, também é possível usar reverso-próximo (rn), reverso-cont. (rc), etapa reversa (rs), reverso-fin.

Elas ainda respeitam os pontos de interrupção que você definiu. 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 é é desnecessário. RR pode rastrear vários processos; após a gravação, é possível ver uma lista usando rr ps e escolher uma para reproduzir com rr replay -f PID.

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