WinDbg にはまる

とある関数で,最初の引数がある定数にマッチしたら,2番目の引数とスタックトレースを出して継続としたかったので,色々とやってみたが,ピント外れの分かりにくい WinDbg のエラーメッセージと,振る舞いのおかげで偉い目にあった。

結果的には次のもので動いた。


bp mymod!MyComponent::CallMyDefWindowProc "j (poi(esp+4)==0x282) '.time;.printf \"wp %x\\n\",poi(esp+8) ;kv;g' ; 'g'"

困った所

  • poi の引数に ebp+8 の様な使い方をしていた,その時は関数の先頭ではなく、ある程度のオフセットがあったので,ebp は使えるかと思ったのだが,これがトラブルの元。対象の関数は leaf という訳でもないが,ebp を使わない物だった。結果,"Memory access error at" に続けて poi の閉じる括弧の後が続く。ググっても,的を射た物が見つからない。結局,スタックポインタを関数内の一に応じて push 命令等を考慮して計算して,底から相対的に引数を見つけることにした。上記の例では関数に入ったばかりで,リターンポインタが積まれたばかりなので,最初の引数は esp+4, 次は esp+8 にあるはず。poi って、有効なレジスタを内部的には判断したりしてるのかもしれないが,エラーはもっと分かりやすく出してほしい。
  • 上記コマンドには条件分岐 (j) があるが,これも久々に使ったのと、ディスプレイがあまり良くなかったので,if, else のボディの区切りにコロンを使ってはまる。セミコロンが正解,でもエラーメッセージの前のカレットが全然見当違いのとこさしてるのではまる。
  • .printf の最初の format 文字列引数は、どうやらダブルクォートでくくる必要があるらしい。既に外側で使っているので,シングルクォートにするがだめ。ダブルクォートにして、さらにエスケープもしないといけない。これで,コマンドの中にパス名とか含めたら地獄だな。 find, findstr が文字列の引数がダブルクォートで括る事を必須にしてるみたいなへんてこな造りだ。やはり、Dos/Windows 系のこの種のパーサーは根本的に間違ってると思う。


収穫は .printf が使える事を見つけた事位か...