メモリ内容の採取
先の採取例では,
そこで,checksum
を想定します。なお,
リスト11 採取対象関数checksum
)
int
checksum(const char* buf)
{
int val = 0;
int i;
int length = 32;
for(int i = 0 ; i < length ; i += 1){
val = (val << 1) ^ buf[i];
}
return val;
}
先述したように,buf
が指しているユーザ空間のメモリ内容を一旦カーネル空間にコピーしてから,
そこで,
リスト12 データ領域内容採取Dスクリプト
pid$target:show_args:checksum:entry
{
this->iobuf = alloca(32);
copyinto(arg0, 32, this->iobuf);
tracemem(this->iobuf, 32);
}
このDスクリプトによって,buf
の指す領域は以下のような形式で表示されます。
図5 データ領域内容の採取
$ dtrace -s watch_arg_mem.d \ -q \ -c './show_args' 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 80 09 05 08 34 00 00 00 ............4... $
上記の D スクリプトにおけるアクション部分は,
- 変数
iobuf
を確保 - 32 バイトのバッファ領域を
( alloca
サブルーチンによって)カーネル空間に確保 iobuf
変数にバッファ領域を参照させるchecksum
関数の引数buf
の指すメモリ領域(ユーザ空間) から, iobuf
の指す領域(カーネル空間) へ32バイト分を ( copyinto
サブルーチンによって)複製 iobuf
の指す領域32バイト分を( tracemem
アクションによって)表示
copyinto
やtracemem
などは,
それではここで初めて出てきたthis
というキーワードは何でしょうか?
Dスクリプトでは,this->VariableName
と記述することで,
上記のDスクリプトiobuf
変数を使用していることになります。
なお,tracemem
に指定するデータ長は,
- ※4)
- Dスクリプトでの変数の扱いについての詳細は第4回で,
可変長領域の内容を表示する方法については第7回で扱う予定です。
戻り値の採取
これまでに説明してきた手法を組み合わせれば,
後は関数の戻り値を採取できれば,
以下のDスクリプトは,show_
中の全ての関数に対して,
リスト13 関数戻り値採取Dスクリプト
pid$target:show_args::return
{
printf("%s()=0x%p", probefunc, arg1);
}
pid
プロバイダでentry
プローブを指定するDスクリプトでは,arg0
やarg1
は関数引数の参照に使用しました。しかし,return
プローブを指定するDスクリプトでは,
arg0
: 関数の戻り先アドレスarg1
: 関数の戻り値
何らかのデータが格納されている領域を指すアドレスが戻り値になっていて,copyinstr
やcopyinto
+ tracemem
などを使用する必要があります。
なお,arg1
の値は,
- 戻り値を持たない
( void
な)関数 - 構造体/
オブジェクトを返却する関数
次回予告
関数フローにおける基本的な情報採取について,
次回は,