2012年05月02日
systemtapのテンプレート
kernelをデバッグするときにsystemtapを利用するのですが、
毎回スクリプトを作るのが面倒くさいのでテンプレートを作成するのを書いてみました(使う場合は、末尾のスクリプトをコピペしてください)。
個人的なスクリプトなので自己責任で利用してください。
使い方は
”./stap-setter.sh [mh] 関数 ” です。
例えば ext4_fill_superが実行されたことを出力したい場合、
./stap-setter.sh ext4_fill_super
と実行します。すると"test.stp"が下記の内容でできあがります。
# stap test.stp でsystemtapを実行します。
裏でext4をmountするとext4_fill_superが呼ばれるので
start
ext4_fill_super called
と出力されます。
printfで関数の呼び出しだけ出力しているのですが、print_backtrace()に置き換えて
バックトレースを見たりもできます。
そこら辺はsystemtapのマニュアルに書いてありますので、別の機会に。
モジュールの場合は -m をつけます。ext3/ext4/jbd/jbd2しか対応してませんが、
他のモジュールも利用する場合は、スクリプト内の配列に追加すればokです。
毎回スクリプトを作るのが面倒くさいのでテンプレートを作成するのを書いてみました(使う場合は、末尾のスクリプトをコピペしてください)。
個人的なスクリプトなので自己責任で利用してください。
使い方は
”./stap-setter.sh [mh] 関数 ” です。
例えば ext4_fill_superが実行されたことを出力したい場合、
./stap-setter.sh ext4_fill_super
と実行します。すると"test.stp"が下記の内容でできあがります。
#!/usr/local/bin/stap
probe begin
{
printf("start\n")
}
probe kernel.statement("ext4_fill_super") {
printf ("ext4_fill_super called\n")
}
# stap test.stp でsystemtapを実行します。
裏でext4をmountするとext4_fill_superが呼ばれるので
start
ext4_fill_super called
と出力されます。
printfで関数の呼び出しだけ出力しているのですが、print_backtrace()に置き換えて
バックトレースを見たりもできます。
そこら辺はsystemtapのマニュアルに書いてありますので、別の機会に。
モジュールの場合は -m をつけます。ext3/ext4/jbd/jbd2しか対応してませんが、
他のモジュールも利用する場合は、スクリプト内の配列に追加すればokです。
#!/bin/bash
func_array=($*)
kallsyms="/proc/kallsyms"
num=0
module=0
filename="test.stp"
mod_array=(ext3 ext4 jbd jbd2)
usage()
{
echo "stap-setting.sh [-mh] func-name ..."
echo "e.g. ./stap-setting.sh ext4_fill_super"
exit 0
}
check_env()
{
if [ -z `which stap` ];then
echo "systemtap is not installed"; exit 1
fi
if [ -e $filename ];then
echo "File name $filename is duplicated"; exit 1
fi
#echo "Ok, check_env are safe"
}
search_func_name()
{
local name=$1
local out=`grep -w $name $kallsyms | awk '{printf $3}'`
local ret=0
# $name does not exist in $kallsyms
[ -z $out ] && ret=1
return $ret
}
add_line()
{
echo "$1" >> $filename
}
add_begin() {
add_line "#!/usr/local/bin/stap"
add_line ""
add_line "probe begin"
add_line "{"
add_line " printf(\"start\n\")"
add_line "}"
}
fill_up_name_with_module() {
local out=""
local name2=$1
for mod in ${{mod_array[@]}mod_array[@]};do
out=`echo $name2 | grep $mod`
if [ $out ];then
add_line "probe module(\"$mod\").function(\"$name2\") {"
add_line " printf (\"$name2 called\n\")"
add_line "}"
fi
done
}
fill_up_name(){
local name=$1
local count=$2
# add "probe begin" to script
[ $count -eq 1 ] && add_begin
if [ $module -eq 0 ];then
add_line ""
add_line "probe kernel.statement(\"$name\") {"
add_line " printf (\"$name called\n\")"
add_line "}"
else
fill_up_name_with_module $name
fi
}
check_env
while getopts ":m:h" GETOPTS
do
case $GETOPTS in
m) module=1
echo "module mode is not tested well...";;
h) usage;;
*) usage;;
esac
done
count=1
for num in ${{func_array[@]}func_array[@]};do #
search_func_name $num
[ $? -eq 1 ] && continue
fill_up_name $num $count
((count++))
done
【Linuxの最新記事】
この記事へのコメント