SSブログ

アセンブラによる無限ループ、再起動の回避 [ドライバ開発]

VMWareなど、仮想マシンを使っていれば特に問題ないのだが、今の開発では、仮想マシンが使えずリモートデバッグで開発している。
 ブート時に読み込まれるドライバのため、不具合を修正するつもりで、ちょっとした記述ミス(変数の初期化忘れなど)によって、マシンが無限再起動や無限ループしてしまうことがたまにある。

普通のドライバであれば、大体以下のパターンで回避できる

・リモートデバッグしているドライバのイメージがちゃんとあって、変数が見れる場合には、変数に適宜入れて回避できる。(特定の無限ループは回避できるが、当然コードの修正はできない)
・手前に手軽にジャンプできる条件文が無く、絶対にあるルーチンに入ってしまうために、回避できない場合もある。通常のデバイスドライバであれば、そのデバイスをはずしてOSを起動し、正常なドライバに差し替えてから再度デバイスを有効にする。
・起動時にF8を連打して、セーフモードで起動し、そのドライバがロードされないようにする(が、これはカーネルモードサービスに対してはあまり有効ではない)

ほとんどの場合は以上の3パターン、特に2つめの場合で済む。しかし、起動時に読み込まれるドライバの場合にはそうはいかない。セーフモードですら呼ばれるほどの重要性があるドライバの開発の場合、セーフモードにしてもやはり呼びだされてしまう。そこで、カーネルモードサービスの開発では、ダミーで何もしないで抜けられるようにしておく。

DriverEntry( ... )
{
 int status = STATUS_SUCCESS;
 __asm int 3;//デバッグモードだったら一時停止するコードを書いておく
 if( status ) {
  return STATUS_UNSUCCESSFUL;
 }

..

return status;
}

起動時にいちいちデバッガが停止するが、こうしておくことで、status変数をデバッガで変えることによって、ドライバがロードされず、無限再起動から抜けられることも多い。

ところが、デバッグ中にうかつにもコンパイルしてしまうと、リモートのイメージとローカルのそれが一致しないため、変数を書き換えることができなくなってしまう。そんなときに、マシン語を使う。メモリ上のコードを書き換えて、エラーが発生したらリターンするルーチンまでジャンプさせることで対応する。ret,jmp、push,cmp程度の命令ですむので、アセンブラに詳しくなくてもどうにかなる。最悪nopで最後のリターンまで埋め尽くせばよい。

上記のようなソースで ... の箇所に例外発生箇所がある場合には、statusと思われる変数に0以外の値を入れて、最後のreturn statusのところにジャンプするようにすれば、間の処理をすべて飛ばせる。

そもそもOSのイメージを作っておくのは当然といわれればそれまでだが、2003対応のバックアップソフトが高すぎるのでこんなことをやらないといかんかった。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

SIMD関係メモ ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。