MSYS環境下でのシステムコールトレーサー?(strace)の使い方

Linuxのそれと微妙に使い方が違うので健忘録です。ヘルプも表示されないので…。
まず、トレースを仕掛けたい実行ファイルがMSYS DLLを使用していることが、strace実行の絶対条件です。具体的には、『「objdump -x 実行ファイル | grep DLL」を実行したとき、「msys-1.0.dll」が表示されること』です。
次に、MSYS DLLがデバッグ用のものになっている必要があります。こちらは、strace実行前に「msys-1.0-debug.dll」を「msys-1.0.dll」へコピーするだけです。
以上の2点の条件が揃わないと、straceを仕掛けても何も得られません。
なお、「msys-1.0-debug.dll」は、オリジナルの「msys-1.0.dll」と比べると、実行性能が非常に劣化するので、通常運用時はオリジナルに戻す必要があります。つまり、コピーする前にオリジナルの「msys-1.0.dll」をバックアップしておく必要があります。また、Linux環境のそれと同様に、「msys-1.0-debug.dll」+トレース実行環境では、処理がシリアライズされるため、問題の現象をうまく捉えられないおそれがあります。ただ一番の問題は、MSYSのstraceはシステムコールトレーサーではなく、MSYS DLLのデバッガツールであることを意識して使わないとならない事です。

前準備

その1 入手

straceおよびmsys-1.0-debug.dllは、通常のインストール状態では用意されていません。このため、個別に入手する必要があります。最新環境を使用している場合は、「mingw-get install msys-core-dbg」を実行すると、必要な実行ファイルやライブラリが入手できます。
それ以外の環境の場合、MinGWプロジェクトのMSYS/Base/msys-coreから、「msysCORE-{バージョン}-msys-{バージョン}-dbg.tar.lzma」をダウンロードします。その後「tar -xf msysCORE-{バージョン}-msys-{バージョン}-dbg.tar.lzma -C /」を実行すると、必要な実行ファイルやライブラリが入手できます。

その2 MSYS DLLの入れ替え

MinGWおよびMSYSのシェルがMSYS DLLを使用しているため、いったんすべてのMinGWシェル/MSYSシェルを終了させてください。終了後、エクスプローラー等で、「C:\MinGW\msys\1.0\bin\msys-1.0.dll」のバックアップを作成後、「C:\MinGW\msys\1.0\bin\msys-1.0-debug.dll」を「C:\MinGW\msys\1.0\bin\msys-1.0.dll」としてコピーしてください。

構文

usage: strace.exe [-dfntu][-b num][-m hex][-o file] 実行ファイル [引数...]
Linuxのstraceには、pid指定をして実行中のプログラムをトレースする方法もありますが、MSYSのstraceにはpid指定のトレースはありません。つまり、実行ファイルを指定して、最初から最後までトレースするスタイルしかないので、注意してください。

オプション説明

-d

直前のトレースログからの差分時間(μ秒)を表示する/表示しない(デフォルトは表示する)。
toggleスイッチとなっており、指定毎に表示の有無が切り替わる。つまり-dでは表示されなくなり、-ddでは表示されるようになる。
なお、絶対時間表示(-tオプション参照)になっている場合は、本オプションは無視され差分時間は表示されない。

-f

実行ファイル内で起動された子プロセスもトレースの対象にする/しない(デフォルトは対象にしない)。
toggleスイッチとなっており、指定毎にトレースの有無が切り替わる。つまり-fでは子プロセスもトレース対象とし、-ffでは実行ファイルのみをトレース対象とする。

-n

Windowsからエラーが報告された場合、そのエラーを番号で表示/文字列で表示する(デフォルトは文字列で表示)。
toggleスイッチとなっており、指定毎に表示形式が切り替わる。つまり-fでは番号表示になり、-ffでは文字列表示になる。

-t

トレースログのタイムスタンプを絶対時間表示にする/経過時間(μ秒)表示にする(デフォルトは経過時間表示)。
toggleスイッチとなっており、指定毎に表示形式が切り替わる。つまり-tでは絶対時間表示になり、-ttでは経過時間表示になる。
絶対時間では、そのトレースログを採取した時刻を「hh:mm:ss」の形式(1時2分3秒に採取した場合、01:02:03)で表示し、「秒」より下の桁は表示しない。経過時間表示では、そのトレースログを採取した時刻を、トレースを採り始めてからの経過した時間(単位:μ秒)で表示する。

-u

オプションとしては指定できるが、目的と実装が一致していないため、使用してはならない。

-b 10進数値

ログファイル(-oオプション参照)を指定している場合、そのファイルの書き込み時に使用するバッファのサイズをバイト単位で指定する。
ログファイルを指定して、本オプションを指定していない場合は、システム規定値で動作する。つまり、大量のログ出力による書き込み遅延がネックになっている場合、本オプションでバッファサイズを調整する必要があるが、それ以外は、特に本オプションを指定しなくても良い。

-m 16進数値

採取するトレースの範囲を選択する(デフォルトは1)。
指定する値(採取するトレース範囲)は、次の値の論理和を16進数値で指定する。

指定値 トレースする内容
00001 現状では08fd1が指定されたものとして動作する。
00002 未実装(_STRACE_FLUSH)
00004 未実装(_STRACE_INHERIT)
00008 未実装(_STRACE_UHOH)
00010 MSYS DLLが外部公開している関数(unixシステムコールに近い)の動作ログ(ソース中のsyscall_printfの部分)を採取する。Linuxのstraceの様な「呼び出し時のログ」ではないことに注意すること。
00020 未実装(_STRACE_STARTUP)
00040 syscall_printfで採取される動作を補足する内容のログ(ソース中のdebug_printfの部分)を採取する。syscall_printfのログを包含していないため、動作を把握するには00010を同時に指定する必要があるかもしれない。また、本値を指定するとログが非常に大きくなるため、使用には細心の注意が必要である。
00080 ファイルディスクリプタ1〜2についての動作ログ(ソース中のparanoid_printfの部分)を採取する。
00100 端末I/Oの動作ログ(ソース中のtermios_printfの部分)を採取する。
00200 select関数の動作ログ(ソース中のselect_printfの部分)を採取する。
00400 MSYS DLLが受信したウィンドウメッセージを採取する。
00800 シグナル処理の動作ログ(ソース中のsigproc_printfの部分)を採取する。
01000 未実装(_STRACE_MINIMAL)
02000 未定義
04000 未実装(_STRACE_EXITDUMP)
08000 致命的なエラーが発生したことを示すログ(ソース中のsystem_printfの部分)を採取する。なお、このログは08000を指定しなくても採取される。
10000 未実装(_STRACE_NOMUTEX)
20000 メモリの確保および解放の動作ログ(ソース中のmalloc_printfの部分)を採取する。
40000 スレッドについての動作ログ(ソース中のthread_printfの部分)を採取する。
80000 使用禁止
-o ログファイル名

トレースログの出力先を指定したファイルへ変更する。
本オプションを指定していない場合は、標準出力にトレースログを出力する。