SystemTap Beginners Guide 4章のメモ

User-Space Probing

SystemTapカーネル向けに作られたが、ユーザー空間のプローブも可能になった。
SystemTapのユーザ空間プローブには、カーネルのutrace拡張が必要である。
詳細は http://sourceware.org/systemtap/wiki/utrace で確認せよ。
現在のカーネルがutraceをサポートしているかどうかは、
"grep CONFIG_UTRACE /boot/config-`uname -r`"を実行して
"CONFIG_UTRACE=Y"と表示されれば、ユーザー空間でのプローブが出来る。

メモのメモ

linux kernel 3.5.0 からユーザー空間でのプローブを行うための機構uprobesが提供された。
このため、linux kernel 3.5.0以上とSystemTap1.8以上であれば、utraceをカーネルに組み込まなくても
SystemTapでユーザー空間のプローブが出来る。

4.1 ユーザー空間イベント

全てのユーザー空間イベントプローブはプロセスと共に始まる。
プロセスイベントはプロセスIDや実行ファイルパスによって、特定の実行中プロセスに限定する事が出来る。
SystemTapはPATH環境変数を参照するので、コマンドラインと実行ファイルの絶対パスの両方を実行に使うことが出来る。
いくつかのユーザー空間プローブイベントでは、debug情報が要求されるため実行ファイルパスかプロセスIDを指定する必要がある。
以下に列挙するprocessイベントのいくつかでは、実行ファイルパスかプロセスIDを指定する必要がある。
以下に列挙されていないprocessイベントでは、実行ファイルパスやプロセスIDの指定はオプションである。

  • process("path").function("function")

ユーザー空間の実行ファイルパスの開始イベント。kernel.function("function")に相当する。
ワイルドカードも使えるし、.returnも使える。

  • process("path").statement("statement")

statementに対する指示。kernel.statement("statement")に相当する。

  • process("path").mark("marker")

pathで定義されている静的なプローブポイントマーカ。ワイルドカードを指定すれば、全てのマーカで単一のプローブが実行される。
静的なプローブポイントは($1,$2, etc)のような数値の引数を持っているかもしれない。
Javaのようなユーザー空間のパッケージは静的なプローブポイントを含んでいる。
静的なプローブポイントを提供するようなパッケージでは、生のユーザー空間マークイベントに対するエイリアスを提供している。
以下はx86_64 Java hotspot JVMのものである。

probe hotspot.gc_begin =
process("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so").mark("gc__begin")
  • process.begin

ユーザー空間プロセスが作成された。プロセスIDか実行ファイルのフルパスによって、限定することが出来る。

  • process.thread.begin

ユーザー空間スレッドが作成された。プロセスIDか実行ファイルのフルパスによって、限定することが出来る。

  • process.end

ユーザー空間プロセスの死亡。プロセスIDか実行ファイルのフルパスによって、限定することが出来る。

  • process.thread.end

ユーザー空間スレッドの破壊。プロセスIDか実行ファイルのフルパスによって、限定することが出来る。

  • process.syscall

ユーザー空間プロセスのシステムコールシステムコール番号は$syscallコンテキスト変数で利用出来、
引数の最初から6つ目までは$arg1から$arg6で利用することが出来る。
.returnサフィックスがあれば、システムコールの戻りで実行される。この時、$returnで戻り値を参照出来る。
プロセスIDか実行ファイルのフルパスによって、限定することが出来る。

4.2 ユーザー空間ターゲット変数

ユーザー空間ターゲット変数は3.3.2と同じ方法でアクセス出来る。
ユーザーとカーネルアドレス空間が分かれているが、"->"演算子は最適なアドレス空間にアクセスする。
ポインター経由でユーザー空間のデータにアクセスする際には、以下の関数を利用出来る。

  • user_char(address)

現在のユーザープロセスで、アドレスにある文字を得る。

  • user_short(address)

現在のユーザープロセスで、アドレスにあるshortを得る。

  • user_int(address)

現在のユーザープロセスで、アドレスにあるintを得る。

  • user_long(address)

現在のユーザープロセスで、アドレスにあるlongを得る。

  • user_string(address)

現在のユーザープロセスで、アドレスにあるstringを得る。

  • user_string_n(address, n)

現在のユーザープロセスで、アドレスにあるstringをnbytesだけ得る。

4.3 User-Space Stack Backtraces

イベントが発生した状況を確認するためには、バックトレースがあると便利である。
SystemTapはバックトレースの表示にデバッグ情報を使っている。この機能はx86用であるため、他のアーキテクチャでは使えない。
バックトレースの表示には"-d 実行ファイルパス"オプションと、共有ライブラリのための-lddオプションが必要である。

例えば、lsコマンドでxmallocが呼ばれた際のユーザー空間のバックトレースが見たい場合には、以下のコマンドを実行する。

stap -d /bin/ls --ldd -e 'probe process("ls").function("xmalloc") {print_ustack(ubacktrace())}' -c "ls /"

実行に失敗する場合には、lsコマンド用のdebuginfoを以下のコマンドでインストールすること。
debuginfo-install coreutils-8.15-7.fc17.x86_64

さらに詳細に見たければ、ucontext-symbols.stpとucontext-unwind.stp tapsetsを参照せよ。
関数の詳細はSystemTap Tapset Reference Manualを参照せよ。