Jockeyの論文を斜め読みしたので簡単に
追記: このソフトはバックエンドにlibdasmというディスアセンブラを使っているようだ。たしかにx86のopcodeの解読なんていちいち作りたくないわな。
結構使いやすそうなんで、気になっているのだがライセンスがよく分からんぞー
- 用途はデバッグ。特に以下の3点はいままでデバッグがめんどかったのでメインターゲット
- 動作が非決定的であり、結果が毎回変わるプログラム
- 長時間動くプログラム、長すぎて何回も再試行できない
- distribeted program. 1台だけデバッガくっつけたら動作が変わってしまうようなもの
- 以下の制約があるよん
- mmapやファイルアクセスが可能だと仮定しているよん
- 共有メモリを用いた他プロセスとの暗黙の通信はcaptureできないよん
- kernel thread を用いた pthread実装をつかうcontext switchのタイミングが制御できないので再生時に前回と違う結果になったりしてうまくいかないよん
- 実装について
- libcのシステムコールの入り口を書き換えてlibjockey.soのそれを呼び出すように(テキストセグメントを)書き換えちゃうよん(time, rscvfrom, selectなど)
- rdtsc命令もcaptureするようにメモリ上のプログラムを改変しちゃうよん
- 各システムコールで再生時に同じ結果を返せるように結果をlogに保存するとともに、途中からの再生をサポートすべくcheckpointを作成するよん
- rdtscパッチを考えると、パッチ動作には時間がかかる(平均約350ミリ秒だそうな)のでオブジェクト毎にどこを書き換えればいいのかの情報をキャッシュするよん
- Exec Shield はOFFにしないと動かないよん
- 非同期シグナルは以下のようにとりあつかうよん
まず、libjockey.so がシグナルを補足、内部のシグナル受け取ったよフラグを立てるとともに、シグナルナンバー、CPUレジスタを保存
次のシステムコールが呼ばれたときに、フラグが立っているのでユーザーアプリのシグナルハンドラをアップコール。
・・・なんでその場でアップコールしちゃいけないんだっけ?
- mmap I/Oの追跡
内緒でぜんぶ read onlyにしておいて、SIGSEGVするたびにwritableにし、また次のシステムコールの入り口でread onlyに書き換える。するとどのページがいつupdateされたか追跡できる。だそーな - ユーザー定義のある関数が呼ばれたときに呼ばれるHook関数を挿入できるよん、そのやり方は(ここ注目!)
現在メモリにmapされているすべてのshared objectにnm、publicな関数のアドレスを調べる。
そのアドレスを決めうってリンクするリンカスクリプトを動的に生成、スタティックリンカ(ld)にかける。
それを適当なアドレス空間にmmapし、ユーザーHook関数を呼び出すようにHook先関数の先頭部分を書き換え。
うーん、強引すぎて感動に屁が出そう
- おいらの疑問
- checkpointをどういう形式で保存しているのかよく分からなかった
- パッチ位置のキャッシュだが、オブジェクトがバージョンアップしちゃったらどうしたらいいのかしら?
追記: このソフトはバックエンドにlibdasmというディスアセンブラを使っているようだ。たしかにx86のopcodeの解読なんていちいち作りたくないわな。
結構使いやすそうなんで、気になっているのだがライセンスがよく分からんぞー
- 関連記事
-
- Hacking Apache HTTP Server at Yahoo! (2006/02/01)
- Jockeyつづき (2006/01/27)
- Jockey (2006/01/26)