SystemTapでrubyのUser-Space Evnetsをフックする
SystemTapでrubyのUser-Space Evnetsをフックしてみる。
環境は以下の通り。
systemtapのインストール
sudo apt-get install systemtap systemtap-runtime systemtap-sdt-dev
利用可能なUser-Space Eventsの確認
stap -L 'process("rubyのパス").provider("ruby").mark("*")'
出力例:
% stap -L 'process("/usr/local/bin/ruby").provider("ruby").mark("*")' process("/usr/local/bin/ruby").provider("ruby").mark("array__create") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("cmethod__entry") $arg1:long $arg2:long $arg3:long $arg4:long process("/usr/local/bin/ruby").provider("ruby").mark("cmethod__return") $arg1:long $arg2:long $arg3:long $arg4:long process("/usr/local/bin/ruby").provider("ruby").mark("find__require__entry") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("find__require__return") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("gc__mark__begin") process("/usr/local/bin/ruby").provider("ruby").mark("gc__mark__end") process("/usr/local/bin/ruby").provider("ruby").mark("gc__sweep__begin") process("/usr/local/bin/ruby").provider("ruby").mark("gc__sweep__end") process("/usr/local/bin/ruby").provider("ruby").mark("hash__create") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("load__entry") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("load__return") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("method__entry") $arg1:long $arg2:long $arg3:long $arg4:long process("/usr/local/bin/ruby").provider("ruby").mark("method__return") $arg1:long $arg2:long $arg3:long $arg4:long process("/usr/local/bin/ruby").provider("ruby").mark("object__create") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("parse__begin") $arg1:long $arg2:long process("/usr/local/bin/ruby").provider("ruby").mark("parse__end") $arg1:long $arg2:long process("/usr/local/bin/ruby").provider("ruby").mark("raise") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("require__entry") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("require__return") $arg1:long $arg2:long $arg3:long process("/usr/local/bin/ruby").provider("ruby").mark("string__create") $arg1:long $arg2:long $arg3:long
SystemTapスクリプトの作成
今回は試しに例外の発生をフックしてみる。
まず以下のようなSystemTapスクリプトを書く。
raise.stp:
probe process("/usr/local/bin/ruby").provider("ruby").mark("raise") { printf("%s %s %d\n", user_string($arg1), user_string($arg2), $arg3) }
以下のコマンドで実行:
sudo stap <SystemTapスクリプト> -c <実行するコマンド>
出力例:
% sudo stap raise.stp -c "ruby --disable-gems -e 'raise rescue nil'" RuntimeError -e 1
RuntimeErrorの発生をフックする事ができた。