Microsoft Auto Code Review(OACR)とは
皆さん、こんにちは。A寿です。
突然ですが、皆さんはものすごい勢いで沖の方に流されたことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。
さて、皆さんは、もうWDK for Windows 7 RTM(Windows Driver Kit (WDK) Version 7.0.0のRTM版)をインストールされましたでしょうか?
WDK for Windows 7 RTMをインストールしてビルド環境を立ち上げると、タスクバーに緑色のアイコンが追加されて驚かれた方もいらっしゃるかと思います。そして、ドライバをビルドしたりしますと、この緑色のアイコンが時々黄色や赤に変わったりして、さらに驚かれた方もいらっしゃるかと思います。これは、 Microsoft Auto Code Review(OACR)というもので、自動的にソースコードを静的に解析するツールです。今回は、このOACRについてご紹介したいと思います。
OACRとは
OACRとは、PREfast for DriversがWDKのビルド環境に統合されたものです。WDKのビルド環境でドライバやアプリケーションをビルドすると、自動的にソースコードの問題を解析してくれます。OACRはバックグラウンドで動作し、CPUを使用する優先度が低く設定されています。なので、これまでと変わらないスピードでビルドを実行することができます。また、これまでPREfastを使うには、自分でビルド環境上で実行する必要がありましたが、今後は、特に自分で意識して実行しなくても、PREfastが実行されます。PREfastについては、すでに、さなえすさんの「ドライバー検証ツール」の回で説明されておりますので、ご興味のある方はそちらも参照していただけると幸いです。
OACRがどのような動きをするかを具体的に説明するために、実際に動かして見てみましょう。
ビルド環境を起動すると、自動的にOACRが起動します。今回は、例として、Windows Win7 x86 Checked Buildを使ってみます。
初回起動時には、ビルド環境のコマンドプロンプト上に下図のようなメッセージが表示されます。
1行目に「Launching OACR monitor」と表示されていますが、このOACRモニターは、下図の赤丸で囲んだ、緑色のアイコンとして、タスクバーに追加されます。
ただ、Windows 7の場合、デフォルトの設定では、OACRモニターのアイコンがタスクバーから隠されてしまっているので、これを表示したい場合は、[隠れているインジケーターを表示します](タスクバー上の白い三角)→[カスタマイズ]をクリックして、「タスクバーに表示するアイコンと通知の選択」の画面で、下図の「通知のみを表示」から「アイコンと通知を表示」に変更します。
また、先ほどのビルド環境のコマンドプロンプトの2行目の表示に、「Starting dirs creation ... Completed.」とありますが、これにより、下図のように、新しく%BASEDIR%(例えば、C:\WinDDK\7600.16385.0)にOACRというフォルダと、その中にx86フォルダとchk_win7_x86フォルダが作成されます。このx86フォルダには、ビルド時にOACRでPREfastが実行された結果のログなどが置かれます。
ちなみに、ビルド環境を閉じても、OACRモニターは起動したままなので、2回目以降に同じビルド環境を起動する時には、ビルド環境のコマンドプロンプトに「OACR monitor running already」と表示されます。もし、OACRモニターを自分で終了させていたら、「Launching OACR monitor」と表示され、初回と同様にOACRモニターのアイコンがタスクバーに表示されます。
さて、OACRモニターのアイコンを右クリックすると、下図のようにメニューがいくつかあることがわかります。
メニューで有効になっている各項目について、簡単にご紹介しましょう。
Closeを選ぶと、OACRモニターを終了させることができます。
About OACR... を選ぶと、下図のように、OACRのバージョン(表示ではVersion 3.0.30122.1)、OACRの設定ファイルoacr.iniの場所(表示ではC:\WinDDK\7600.16385.0\bin\x86\oacr\oacr.ini)などがわかります。
Statusを選ぶと、下図のように、現在OACRが監視しているプロジェクト(sourcesファイルで定義されたビルドするファイルの集合、1つのドライバやアプリを作る単位とお考えください)に警告やエラーがあるか(表示ではNo projects with warning log)、ビルド時にソースコードの解析をバックグラウンドで行うために、そのジョブをキューに入れますが、そこで待機しているジョブはあるか(表示ではNo projects with pending queue)、OACR Monitorの状態(表示ではMonitor: Running)などがわかります。
Snoozeを選ぶと、一時的に、OACRモニターを無効にできますが、一時間後に再度有効になります。
OACRによるソースコードの問題の検出
それでは、ビルド環境のコマンドプロンプトに戻り、WDKのtoasterサンプルをビルドして、OACRがソースコードの問題をどう検出するのかを見てみましょう。toasterサンプルの場所は、これまでと同様%BASEDIR%\src\general\toasterの下にありますが、少しフォルダの構成が変わりました。WDK for Windows 7 RTMでは、これまで%BASEDIR%\srcフォルダの下でkmdfやumdfのフォルダとして別れていた、Kernel Mode Driver FrameworkやUser Mode Driver Frameworkで作られたサンプルが、各カテゴリに含まれるように、編成しなおされたからです。(なので、フォルダ構成に変更があったのは、toasterだけではありません。ご自身に関係のあるフォルダにどのような変更が行われたか、ご興味がありましたら、ご確認ください。)
今回は、toasterのWDMのバスドライバを使ってみようと思います。
cd C:\WinDDK\7600.16385.0\src\general\toaster\wdm\bus |
をビルド環境のコマンドプロンプトで実行し、対象のフォルダに移動してください。
そこで、
build |
と実行します。すると、buildは先に完了(正常終了)し、OACRは次の図のように、Machineがbusy状態のため、idleになるまでソースコードの解析の実行を待ちます。
待っている間、アイコンを右クリックしてStatusを見ると、次の図のように、DaemonのQueueに入れられていることがわかります。
もし、解析の実行をすぐに行いたい場合は、次の図のように、OACRモニターを右クリックして、Check Nowを選んで、プロジェクト名である「WDKSample:x86chk」を選ぶと実行できます。ちなみに、この”プロジェクト名“は、デフォルトの設定として、%BASEDIR%の下でビルドすれば「WDKSamples:x86chk」になり、それ以外のフォルダでビルドすれば「root:x86chk」となります。
解析が行われた結果、ソースコードに問題があると判断された場合は、次の図のように、通知が行われます。
先ほど、ビルドは正常に完了していたので、ビルド時に見つからないソースコードの問題を、OACRが見つけてくれることがわかります。
問題の内容を見るには、次の図のように、OACRモニターを右クリックして、View Errorsを選んで、プロジェクト名を選びます。
すると、次の図のように、PREfastのMessage List画面が表示されます。
リストアップされているエラーの詳細を確認したい場合は、各エラーをダブルクリックします。
まずは、Message List画面の一番上のエラーを見てみましょう。次の図のように、View Annotated Source画面が表示されます。
Warning 6291が出ており、ビット演算として、!が|よりも高い優先度を持つため、||か(!(x | y))のどちらかを使うように、と書いています。図の赤字で表示されている、busenum.cの73行目でこの問題が発生しているようですが、赤字で表示されている部分には、この問題に該当しそうな記述はありません。そのため、Bus_KdPrint_Def()というマクロの中に問題があるようです。
そこで、Bus_KdPrint_Def()を定義している、busenum.hを見てみましょう。
Bus_KdPrint_Def()の定義は、112行目から始まっていますが、同様の処理を行っているところとして、101行目から116行目に次のようなマクロがありました。
101 #define Bus_KdPrint(_d_,_l_, _x_) \ 102 if (!(_l_) | (_d_)->DebugLevel & (_l_)) { \ 103 DbgPrint ("BusEnum.SYS: "); \ 104 DbgPrint _x_; \ 105 } 106 107 #define Bus_KdPrint_Cont(_d_,_l_, _x_) \ 108 if (!(_l_) | (_d_)->DebugLevel & (_l_)) { \ 109 DbgPrint _x_; \ 110 } 111 112 #define Bus_KdPrint_Def(_l_, _x_) \ 113 if (!(_l_) | BusEnumDebugLevel & (_l_)) { \ 114 DbgPrint ("BusEnum.SYS: "); \ 115 DbgPrint _x_; \ 116 } |
これらを見ると、確かに102,108,113行目に、「if ( ! (_l_) | ...」という部分があります。このコードでは「!」の有効範囲を明示していないために、コーディングしている人の設計の意図と異なるコーディングをしている可能性があることをOACR(PREfast)は指摘しています。
そこで、これらの行を、以下の赤字のように変更してみました。
101 #define Bus_KdPrint(_d_,_l_, _x_) \ 102 if ( ( !(_l_) ) | (_d_)->DebugLevel & (_l_)) { \ 103 DbgPrint ("BusEnum.SYS: "); \ 104 DbgPrint _x_; \ 105 } 106 107 #define Bus_KdPrint_Cont(_d_,_l_, _x_) \ 108 if ( ( !(_l_) ) | (_d_)->DebugLevel & (_l_)) { \ 109 DbgPrint _x_; \ 110 } 111 112 #define Bus_KdPrint_Def(_l_, _x_) \ 113 if ( ( !(_l_) ) | BusEnumDebugLevel & (_l_)) { \ 114 DbgPrint ("BusEnum.SYS: "); \ 115 DbgPrint _x_; \ 116 } |
それでは、再度ビルドして見ましょう。
ビルド環境のコマンドプロンプトで
build -cZ |
を実行します。
ビルド完了後、しばらくすると、ソースコードの解析が実行され、次の図のように、問題がないことが表示されました。つまり、ソースコードに潜在する問題を解決できたことになります。
以上のように、OACRは、ビルド時に自動的にPREfastでソースコードの実装の問題点を見つけてくれる、すばらしいツールです。まだWDK for Windows 7 RTMを使用されていない方は、ぜひご利用いただき、ご自身のソースコードの質を向上していただければと思います。
また、今回は、概要だけで長くなってしまったので、OACRのカスタマイズ(有効/無効やプロジェクトごとの設定など)についてはご紹介しませんでしたが、ご興味のある方は以下のドキュメントをご参照いただければ幸いです。機会があれば、こちらもご紹介してみたいと思っています。
Windows Auto Code Review (OACR)
https://msdn.microsoft.com/en-us/library/dd445214.aspx
Configuring Microsoft Auto Code Review (OACR)
https://msdn.microsoft.com/en-us/library/dd445213.aspx
Customizing a Microsoft Auto Code Review (OACR) Project
――――――――――――――――
【閑話休題】皆さんはものすごい勢いで沖の方に流されたことはありますか?
残念ながら、離岸流の話ではありません。もし離岸流を体験した話だったら、体が非常に丈夫な方ならともかく、私は生きていないと思います。
何の話かといいますと、ウィンドサーフィンの話です。私は、数年前の9月に一度だけ、ウィンドサーフィンの初心者向けの教室に参加したことがあります。初心者向けのウィンドサーフィンのサーフボードは、まるでイカダのような形で、非常に安定しており、その時の風がすごくいい感じなのもあって、しばらくは岸と並行に、行ったり来たりしていました。
先生も、9月には余り生徒がいないこともあって(実際その時の受講者は私一人でした)、海上で近くに寄ってきた時には必ず「初心者なのに、うまいねー。ぜひ続けるべきだよ」と、目的が見え見えのお世辞を言っては離れていくのを繰り返していました。
ただ、調子に乗りやすい性格なのもあり、海上を何往復もしているうちに、ついうっかり帆で風をうける方向を誤り、すごい勢いでぐんぐん沖の方に流されていきました。先生も、指の爪か米粒くらいの大きさに見え、こちらに気づいているかどうかすらわかりません。
「やばい、先生とあんなに遠く離れてしまった。これは自力で戻れなかったら、どうなるんだ?」と、怖くなり、必死に帆で風を受けて、岸になんとかたどりついたのでした。皆様も、先生の見え見えなお世辞にはお気をつけください。