デバッグにあると便利なシンボルとは?
シンボルとは?
シンボルとは、プログラムのアドレスと可読なソースコード上の名前 (シンボル) を対応させるためのものです。
またそれだけではなく、シンボルには FPO 情報を含むため、FPO フレームが混在する場合でもスタックを正しくたどることができるようになります。シンボルは拡張子 pdb のファイルに格納されています。以前のバージョンのものですと、このほかに dbg という拡張子を持つものもありますが、それは現在では pdb へのポインタを含むだけの役割を持っています。今後は pdb のみになってゆくと思われます。実際に WindowsXP ではすべて pdb ファイルに切り替えられています。
百聞は一見にしかず。始めに正しいシンボルが設定されている環境のデバッガの出力を見てください。
0:000> kv ChildEBP RetAddr Args to Child 0012ff1c 00401014 00000000 00407030 0040703c USER32!MessageBoxA (FPO: [4,0,0]) 0012ff30 00401025 00401104 00400000 00000000 Call01!ShowMessage+0x14 (FPO: [0,0,0]) 0012ff34 00401104 00400000 00000000 00141f16 Call01!WinMain+0x5 (FPO: [4,0,0]) 0012ffc0 77e3eb69 77f82402 77f754f8 7ffdf000 Call01!WinMainCRTStartup+0xce 0012fff0 00000000 00401036 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
次に、比較のためシンボルが無い場合のデバッガの出力を見てください。
0:000> kv *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINXP\system32\kernel32.dll - ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 0012ffc0 77e3eb69 77f82402 77f754f8 7ffdf000 USER32!MessageBoxA 0012fff0 00000000 00401036 00000000 78746341 kernel32!CreateProcessInternalW+0x1177
これらは、アプリケーションをまったく同じ箇所で停止させてアプリケーションの状態を見たものです。 アプリケーションは完全に同じ状態であるにもかかわらず、デバッガで見える状態はこれだけ違ってしまいます。
デバッガのコマンドに関する詳細については後ほどご説明しますので、ここでは細部にこだわらなくても構いません。 しかし、ぱっと見ただけで出力される情報がまったく異なっていることがお分かりになるでしょう。 何しろシンボルがない場合の出力はフレームが 2 つしか出力されていないのに、 シンボルがある場合は 5 つのフレームが出力されています。これだけわかる情報が違ってきます。
言うまでもなく、実際に実行された軌跡を正しく示しているのはシンボルがある場合の出力です。 ですから、シンボルが無い場合は本当の実行の様子を知ることは非常に困難といえます。
シンボルの入手
インターネットに接続している状態であれば、マイクロソフトのモジュールに関して、特に OS については 必要に応じてダウンロードしてくることが可能です。
後述のシンボルパスを設定してください。
また、カスタムのモジュールに関するシンボルファイルは、開発者にプログラム生成時に 作成・管理するよう依頼しておくと良いでしょう。
必要に応じてダウンロードするのではなく、まとめてパッケージをダウンロードしておくには こちらからダウンロードできます。
シンボルパス
デバッガがシンボルファイルを探してくるパスのことをシンボルパスといいます。 デフォルトでは %SYSTEMROOT%\Symbols です。 その他、環境変数 _NT_SYMBOL_PATH にシンボルパスを設定しておく方法や、実行時に .sympath コマンドでシンボルパスを設定することができます。
インターネットを経由してシンボルファイルを必要に応じてダウンロードするための方法は次の通りです。
- C:\websymbols というディレクトリを作成します。
- システム環境変数 _NT_SYMBOL_PATH を作成します。
- 値を srv*C:\websymbols*http://msdl.microsoft.com/download/symbols とします。
シンボルサーバーの構成
最新のデバッガではシンボルサーバーをサポートしています。用語はちょっと紛らわしいかもしれませんが、 デバッガがシンボルを探し当てるためのモジュール symsrv.dll のことをシンボルサーバー (SymSrv) といい、 実際にシンボルが配置してある場所をシンボルストア (SymStore) といいます。 シンボルパスとして、シンボルサーバー経由でシンボルストアを指定すると自動的に適切なシンボルを取得してくれる、というわけです。
Debugging Tools for Windows にはシンボルストアを構築するツールとして SymStore が提供されています。 SymStore はシンボルのルートを C:\symbols とすると以下のようなの構造のフォルダを作成します:
<シンボルルート> = C:\symbols <シンボルファイル名> <タイムスタンプ> <タイムスタンプ2> ... <タイムスタンプn>
SymStore を構築するには Debugging Tools for Windows に付属している SymStore.exe ユーティリティを使います。 次のようなコマンドで実行すればよいのです。
> symstore add /r /p /f \\host1\symfiles\windows\xp\rtm.chk /s \\host1\symbols /t "WindowsXP RTM Checked" .......................................................................... SYMSTORE: Number of pointers stored = 3711 SYMSTORE: Number of errors = 0 SYMSTORE: Number of ignored files = 41
ここで、\\host1\symfiles\windows\xp\trm.chk はシンボルファイルがおいてあるパス、\\host1\symbols はシンボルルートです。
ここでは、UNC で接続して他の人もシンボルが使えるようにマシン名も UNC 名で指定しています。
シンボルストアのメンテナンス状況は、<シンボルルート>\000admin フォルダに記録されます。
トランザクションの削除
シンボルストアへの一連の要求それぞれはトランザクションといいます。ある時点のトランザクションを取り消すには次のように del オプションをつけて SymStore を使います。
> symstore add /p /r /f \\host1\symfiles$\test\winsock /s Q:\symbols /t "WinSock Test Program" /v "1.0.0.1" /c "テストです" /o SYMSTORE: Number of pointers stored = 10 SYMSTORE: Number of errors = 0 SYMSTORE: Number of ignored files = 0 > symstore del /i 0000000001 /s Q:\symbols
これではじめのコマンドで作成したシンボル (への参照) が削除されます。なお、ここで指定したトランザクション番号は 000admin フォルダに記載されているものです。