SystemTapのお勉強・その2 〜Embedded C編〜

前回の記事ではEmbedded Cについて書かなかったので、そのあたりの補足記事として第二弾。

デバッグプリントを行うscriptで、変数の値を表示するだけじゃなくてマクロや関数の実行結果が知りたい、なんて事もあったりする。
その場合でも、SystemTapは元コードを変えずにscript側だけで対処出来るように、Cのコードを埋め込む事が出来るようになっている。

で、書いてみた。
%{から}%までがEmbedded Cのコードになっている。
コードの書き方は普通にカーネルのCなだけ。
但し、THIS->__retvalueとかTHIS->変数名とか妙なのがあったり。

使うときは、普通にget_waitdata($sk)とか書けばよろしい。

%{
#include <net/sock.h>
%}

function get_wq_has_sleeper:long (sk:long) %{
	struct socket_wq *wq;

	rcu_read_lock();
	wq = rcu_dereference(((struct sock *)THIS->sk)->sk_wq);
	THIS->__retvalue = wq_has_sleeper(wq);
	rcu_read_unlock();
%}

function get_waitdata:long (sk:long) %{
	THIS->__retvalue =
		test_bit(SOCK_ASYNC_WAITDATA,
			&((struct sock *)THIS->sk)->sk_socket->flags);
%}

probe kernel.function("sk_wait_data").return {
	printf("%s:%s sk:%p rc:%d wq_has_sleeper:%d waitdata:%d\n",
		execname(), probefunc(), $sk, $return, get_wq_has_sleeper($sk),
		get_waitdata($sk))
}

probe kernel.function("sock_def_readable") {
	printf("%s:%s sk:%p wq_has_sleeper:%d waitdata:%d\n",
		execname(), probefunc(), $sk, get_wq_has_sleeper($sk),
		get_waitdata($sk))
}