これまでの連載における説明では、pid
プロバイダが提供するプローブentry
およびreturn
)
しかし、
そこで、
今回は、
ソースファイルの準備
以下の手順で必要となるソースファイルを準備します。
プロバイダの定義
何をおいても、
リスト1 独自プロバイダの定義
(checkpoint.
)
provider checkpoint {
pass(const char* filename, int lineno);
};
プロバイダcheckpoint
が提供するプローブpass
は、
プログラムの要所要所に埋め込まれたプローブ位置において、ファイル名と行番号情報を採取することで、実行時にどのような経路を通過したのかを知る
つまり、
なおプロバイダ定義を記述する際には、{ }
" の後ろ)
ヘッダファイルの生成
独自プロバイダを定義したならば、dtrace
コマンドを実行してください。
図1 ヘッダファイルの生成
(checkpoint.
)
$ dtrace -s checkpoint.d -h
独自プロバイダを定義したDスクリプトの指定-s
" オプション)-h
" オプションを指定することで、checkpoint.
が生成されます。
:
#define CHECKPOINT_PASS(arg0, arg1) \
__dtrace_checkpoint___pass(arg0, arg1)
:
:
extern void __dtrace_checkpoint___pass(char *, int);
:
"-h
"オプション指定によってdtrace
コマンドが生成するヘッダファイルでは、
通常は、
リスト2の例に見られるように、__
)
ユーティリティヘッダの定義
先述したように、dtrace
コマンドによって生成されたヘッダファイルと、pass
のようなプローブの場合、checkpoint_
を定義しましょう。
リスト3 ユーティリティヘッダの作成
(checkpoint_
)
#include "checkpoint.h"
#define DTRACE_CHECKPOINT_PASS() \
CHECKPOINT_PASS(__FILE__, __LINE__)
CHECKPOINT_
マクロを直接使用するのではなく、DTRACE_
マクロを使うことで、
Cプログラムの実装
今回独自に定義したpass
プローブの埋め込み対象として、main()
に持つプログラムを想定します。
リスト4 プローブ埋め込み対象プログラム
(branch_
)
if(argc < 2){
DTRACE_CHECKPOINT_PASS();
}
else{
int val = atol(argv[1]);
DTRACE_CHECKPOINT_PASS();
if(val < 10){
DTRACE_CHECKPOINT_PASS();
}
else{
DTRACE_CHECKPOINT_PASS();
}
}
DTRACE_CHECKPOINT_PASS();
この実装では与えられた引数に応じて条件分岐を行いますが、pid
プロバイダによる関数フロー採取では、
そこで、pass
プローブを使用することで、
実行可能ファイルの生成
Cプログラムのコンパイル
プローブ埋め込み対象のCプログラム
$ cc -c branch_by_arg.c
ここでのコンパイルにはDTraceの独自プローブ埋め込みの影響はありませんから、
Cプログラムのリンク
コンパイルによって生成された、
$ cc -o branch_by_arg branch_by_arg.o Undefined first referenced symbol in file __dtrace_checkpoint___pass branch_by_arg.o ld: fatal: symbol referencing errors. \ No output written to branch_by_arg $
上記実行例で、checkpoint.
におけるCHECKPOINT_
マクロ)
dtrace
コマンドにより生成されたのはヘッダファイルのみですし、
実はユーザプログラムに独自プローブを埋め込む場合、dtrace
コマンドによる前処理を行う必要があります。
dtrace
コマンドによるリンク前処理は、-G
"オプションと、
dtrace
コマンドによるリンク前処理$ dtrace -s checkpoint.d -G branch_by_arg.o
"-G
"オプションが指定された場合、dtrace
コマンドは以下の処理を実施します。
- 列挙されたオブジェクトファイルから、
プローブ (=" __
"関数)dtrace_* 呼び出しを除去 - 除去したプローブ呼び出しに関する情報をまとめ、
それを格納したオブジェクトファイル (この場合は checkpoint.
)o を生成
前処理が完了したなら、dtrace
コマンドにより生成されたオブジェクトファイルを含めて、
$ cc -o branch_by_arg branch_by_arg.o checkpoint.o
リンク時オプションに関しても、
なお、dtrace
コマンド+"-G
"オプションによる前処理は、
一部のソースファイルを改変してから再度リンクを行う場合、make
コマンド等で自動化する場合には、
プローブからの情報採取
独自に定義したプロバイダからの情報採取の要領は、pid
プロバイダの場合と同じ
リスト5に、checkpoint
プロバイダのpass
プローブを使用するDスクリプトの例を示します。
pass
プローブを使用するDスクリプトcheckpoint$target:$1::pass
{
printf("%s:%d:%s\n",
copyinstr(arg0), arg1, probefunc);
}
それでは、
pass
プローブからの情報採取$ dtrace -s watch_checkpoint.d \ -q \ -c './branch_by_arg 13' branch_by_arg.c:15:main branch_by_arg.c:21:main branch_by_arg.c:25:main $
引数によって分岐した先でDTRACE_
マクロを通過するつど、
Emacsやviのエラー行ジャンプ機能と併用すれば、
次回予告
今回は独自プロバイダの定義を行いましたが、
定義/
次回は、