Chromium Chronicle #13: RR によるタイムトラベル デバッグ

エピソード 13: Christian Biesinger、ウィスコンシン州マディソン(2020 年 3 月)
前のエピソード

デバッガで同じテストを何度も実行していませんか? どうして不正な状態になったのかを 解明しようと思いませんか?便利なツールがあります インストールと設定が簡単で、実行トレースを記録して、 gdb に新たな魔法の力が加わります。1 つ後ろに下がる、後ろに下がる、場所を確認する 変数の値が変更された、またはオブジェクトで関数が最後に呼び出された日時 (条件付きブレークポイントを使用)。

Linux では、rr を使用します。sudo apt-get install rr を使用してインストールするか、 https://rr-project.org/ から入手できます。

これは正式にはサポートされていませんが、非常に便利です。rr の仕組みは次のとおりです。 最初にトレースを記録してから再生します。

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

リプレイのたびにタイミングとポインタのアドレスが変わらないという便利さ 表示されます。rr pack を使用してトレースをポータブルにできます。これにより、 別のマシンにコピーしてそこで再生することも、後で 再コンパイルします。continue を使用してプログラムを実行します。通常の GDB コマンド -bnextwatch など。ただし、 逆方向rn)、逆連続rc)、逆ステップrs)、 reverse-fin

これらは、引き続き設定したブレークポイントに従います。例:

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

この例では、わかりやすくするために --single-process を使用していますが、 不要ですRR は複数のプロセスをトレースできる。録画後に rr ps を使用してリストを表示し、rr replay -f PID でリプレイするリストを選択します。

RR はさまざまな方法で活用できます。使用できる他のコマンドがあります。 たとえば現在地のイベント番号や rr replay -Mなどです これにより、各行のプロセス ID とイベント番号で stdout にアノテーションが追加されます。詳しくは、 RR のウェブサイトとドキュメントをご覧ください。