これまでの連載における説明では、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
"
前処理が完了したなら、 リンク時オプションに関しても、 なお、 一部のソースファイルを改変してから再度リンクを行う場合、 独自に定義したプロバイダからの情報採取の要領は、 リスト5に、 それでは、 引数によって分岐した先で Emacsやviのエラー行ジャンプ機能と併用すれば、 今回は独自プロバイダの定義を行いましたが、 定義/ 次回は、-G
"オプションが指定された場合、dtrace
コマンドは以下の処理を実施します。
__
"関数)checkpoint.
)dtrace
コマンドにより生成されたオブジェクトファイルを含めて、$ cc -o branch_by_arg branch_by_arg.o checkpoint.o
dtrace
コマンド+"-G
"オプションによる前処理は、make
コマンド等で自動化する場合には、プローブからの情報採取
pid
プロバイダの場合と同じ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_
マクロを通過するつど、次回予告