Mona デバッグ用に syscall_set_watch_point を追加しました

これは実験的な機能です。近い将来変更が行われるでしょう。

これは何か?

任意のリニアアドレスにハードウェアブレークポイントを1つセットすることができます。
特定のリニアアドレスの実行/読み書きをトリガにして情報を取得します。
これを利用して例えば、変数の意図しない書き換えの瞬間を捕まえることができデバッグに役立つでしょう。

挙動

ブレーク条件が揃うとカーネルはその時点での

  • プロセス名
  • スレッドID
  • レジスタ
  • リニアドレス
  • リニアアドレスに保持されている値

をログに記録しすぐに実行を再開します。

一般的なブレークポイントと違い、実行が実際にブレークされる訳ではないことに注意してください。
これは現時点での Mona の特有の制限です。

使いかたの例

ある変数 hoge の書き換えを捕まえたい場合

// ブレークポイントを設定
syscall_set_watch_point(&hoge, DEBUG_BREAK_ONLY_ON_WRITE);

...
// ブレークポイントを解除
syscall_remove_watch_point();

第一引数にリニアアドレスを、第二引数にブレーク条件フラグを指定します。
ブレーク条件フラグは以下の4種類。

DEBUG_BREAK_ONLY_ON_EXECUTE 命令実行時にのみブレーク
DEBUG_BREAK_ONLY_ON_WRITE データ書き込み時にのみブレーク
DEBUG_BREAK_ONLY_ON_IO I/O 読み取りと書きこみ時にブレーク
DEBUG_BREAK_ONLY_ON_READ_WRITE データ読み取りと書き込み時にブレーク

ログ出力例

===== debug fault start ===========================================================
address=0xA003784C value=0x90160000
name=HAPPY.EX5 tid=78
eax=0x00000000 ebx=0x0000004E ecx=0x00000000 edx=0x00000000
esp=0xEF7FE844 ebp=0xEF7FE87C esi=0x90160000 edi=0x00001000
cs =0x0000002B ds =0x00000033 ss =0x0000003B cr3=0x0034C000
eflags=0x00000286 eip=0xA002CFE7
===================================================================================

制限

  • 現状では1つしかハードウェアブレークポイントセットできません
  • ブレークポイントはグローバルで1つしか保持しませんので全てのスレッドで共有されます。
  • 実際に「ブレーク」することはなく、ブレーク条件が発生するとログを記録するだけです。