Chromium Chronicle n.o 13: Depuración de viaje en el tiempo con RR

Episodio 13: de Christian Biesinger en Madison, WI (marzo de 2020)
Episodios anteriores

¿Ves que ejecutas la misma prueba una y otra vez en el depurador? tratando de averiguar cómo quedó en mal estado el código? Tenemos una herramienta para ti. Es fácil de instalar y configurar, registra un seguimiento de ejecución y te brinda nuevos poderes mágicos para gdb. Dar un paso hacia atrás, correr hacia atrás, ver dónde variables cambiaron su valor o cuándo se llamó a una función por última vez en un objeto (con puntos de interrupción condicionales).

En Linux, puedes usar rr. Instala con sudo apt-get install rr o de https://rr-project.org/.

Esto no es compatible oficialmente, pero es muy útil. rr funciona así primero registras un seguimiento y, luego, vuelves a reproducirlo.

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, las direcciones de sincronización y puntero permanecen iguales cada vez que vuelves a reproducir una app. el mismo seguimiento. Los seguimientos pueden ser portátiles usando rr pack para que copiarlos en otra máquina y volver a reproducirlos allí, o incluso después volver a compilar. Ejecuta el programa con continue. Puedes usar todas las métricas Comandos de GDB -b, next, watch, etc. Sin embargo, también puedes usar reverse-next (rn), reverse-cont (rc), reverse-step (rs) reverse-fin;

Estos seguirán respetando cualquier punto de interrupción que hayas establecido. Por ejemplo:

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

En este ejemplo, usé --single-process por simplicidad, pero es no es necesario. El RR puede hacer un seguimiento de varios procesos; después de grabar, puedes ver una lista con rr ps y elegir uno para volver a reproducir con rr replay -f PID

La respuesta ante incidentes puede ser útil de muchas formas. Hay otros comandos que puedes usar, como cuándo averiguar el número de evento en el que te encuentras o rr replay -M para anotar stdout con un ID de proceso y un número de evento para cada línea. Consulta el sitio web y la documentación de RR para obtener más detalles.