前回は,
今回は,
なお,pid
プロバイダを使用する場合にも利用可能です。
可変長領域ダンプの採取
まずは,
採取対象の準備
まずはリスト1に示す独自プロバイダuserio
を定義するものと仮定します。
リスト1 プロバイダ定義userio.
)
provider userio
{
probe readin(void* buf, size_t len);
probe writeout(void* buf, size_t len);
};
userio
プロバイダが提供するプローブは,readin
プローブなら実際のI/writeout
プローブなら実際のI/
プロバイダを定義したなら,
- ヘッダフィルの生成
- 採取対象ソースファイル
( read_
)n_write. c の作成 - 採取対象ソースファイルのコンパイル
( read_
の生成)n_write. o dtrace
コマンドによるリンク前処理( userio.
の生成)o - 採取対象実行可能バイナリのリンク
( read_
の生成)n_write
作業手順例を図1に示します。
図1 採取対象実行可能バイナリの生成
$ dtrace -s userio.d -h (1) ※read_n_write.cの作成(2) $ cc -c read_n_write.c (3) $ dtrace -s userio.d -G read_n_write.o (4) $ cc -o read_n_write read_n_write.o userio.o (5) $
tracemem()
の問題点
第2回でデータ領域内容の採取に使用したDスクリプトをリスト2に再掲します。
リスト2 データ領域内容採取Dスクリプト
pid$target:show_args:checksum:entry
{
this->iobuf = alloca(32);
copyinto(arg0, 32, this->iobuf);
tracemem(this->iobuf, 32);
}
tracemem()
は,
また,tracemem()
を繰り返す,
しかし,
数キロバイトまでの対応で割り切ることができるのであれば,tracemem()
による固定長のダンプを,
可変長領域ダンプの実現
さて,
ここでは,
- スクリプト中の各節は,
記述順序に実行される - 述語
(=前提条件) 記述には, 改変を伴う式を記述することができる
繰り返し処理の大枠の構造を,
リスト3 擬似的な繰り返し処理
inline uintptr_t width = 128;
/* 節 (1) */
userio$target:$1::
{ self->offset = - width; }
/* 節 (2) */
userio$target:$1::
/(self->offset += width) < arg1/
{ ※ self->offset は 0 }
/* 節 (3) */
userio$target:$1::
/(self->offset += width) < arg1/
{ ※ self->offset は 128 }
/* 節 (4) */
userio$target:$1::
/(self->offset += width) < arg1/
{ ※ self->offset は 256 }
:
(以下,同じ記述の繰り返し)
:
冒頭の"inline int width = 128;
"は,
第1節で"- width
",self->offset
" 変数は,self->offset += width
"記述により,
つまり,
この方法による擬似的な繰り返しが,self->offset
"変数の値が有効値(この例ではarg1
)を越えた後も,
なお,self->offset
" の値をわざわざ負の値に初期化しているのは,self->offset
"が0の場合の処理を特別扱いしないことで,
実際に可変長領域をダンプするDスクリプトをリスト4に示します。
リスト 4 可変長データ領域内容採取 D スクリプト
inline uintptr_t width = 128;
userio$target:$1::
{
printf("addr=0x%p", arg1);
self->offset = - width;
}
userio$target:$1::
/(self->offset += width) < arg1/
{
self->buf = alloca(width);
copyinto(arg0 + self->offset, width, self->buf);
printf("+0x%p -", self->offset);
tracemem(self->buf, width);
}
:
(以下,同じ記述の繰り返し)
:
このスクリプトによる実行例を図 2 に示します。
図2 可変長データ領域内容の採取
$ dtrace -s watch_io.d \ -c './read_n_write ofile 400 300' \ read_n_write \ < ./read_n_write dtrace: script 'watch_io.d' matched 10 probes CPU ID FUNCTION:NAME 0 60346 main:readin addr=0x8062a10 0 60346 main:readin +0x0 - 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 0: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 .ELF............ 10: 02 00 03 00 01 00 00 00 cc 10 05 08 34 00 00 00 ............4... 20: 48 38 00 00 00 00 00 00 34 00 20 00 06 00 28 00 H8......4. ...(. 30: 26 00 25 00 06 00 00 00 34 00 00 00 34 00 05 08 &.%.....4...4... 40: 00 00 00 00 c0 00 00 00 c0 00 00 00 05 00 00 00 ................ 50: 00 00 00 00 03 00 00 00 f4 00 00 00 00 00 00 00 ................ 60: 00 00 00 00 11 00 00 00 00 00 00 00 04 00 00 00 ................ 70: 00 00 00 00 fd ff ff 6f 08 01 00 00 08 01 05 08 .......o........ 0 60346 main:readin +0x80 - 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 0: 00 00 00 00 10 00 00 00 00 00 00 00 04 00 00 00 ................ 10: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 05 08 ................ 20: 00 00 00 00 a9 23 00 00 a9 23 00 00 05 00 00 00 .....#...#...... 30: 00 00 01 00 01 00 00 00 ac 23 00 00 ac 23 06 08 .........#...#.. 40: 00 00 00 00 6c 02 00 00 58 06 00 00 07 00 00 00 ....l...X....... 50: 00 00 01 00 02 00 00 00 40 24 00 00 40 24 06 08 ........@$..@$.. 60: 00 00 00 00 58 01 00 00 00 00 00 00 07 00 00 00 ....X........... 70: 00 00 00 00 2f 75 73 72 2f 6c 69 62 2f 6c 64 2e ..../usr/lib/ld. ....(以下略)
この例では,readin
プローブを契機に,
なお,copyinto()
サブルーチンに指定するサイズ情報は,
リスト5 サイズ指定超過の防止
copyinto(arg0 + self->offset,
(arg1 - self->offset < width
? arg1 - self->offset
: width),
self->buf);
この記述により,width
よりも小さい場合には,copyinto()
アクションによるカーネル空間への取り込み対象となります。
copyinto()
アクションによるユーザ空間からカーネル空間へのコピーの際に,
サイズ指定をリスト5のように記述することで,
なお,a ? b : c
"形式の"条件式"
- ※1)
- 「3項式」
と呼ばれる場合もあります