ftraceについて調べる(前回からの続き)
ftraceの仕組みを調べるためにググっていたら、http://bit.ly/9cGM9d という論文を発見。
早速読んでみる。
ftraceはgcc の -pgオプションを利用して、関数の入り口でmcount()という関数をコールするようにしている。
(-pgはプロファイラなどのために用意されたオプションで、このオプションでコンパイルされた関数は入り口でmcount()という関数を呼ぶようになるらしい)
そして、各CPUアーキテクチャごとに定義されたmcount()の中でスタックを弄り、mcount()呼び出し元の関数が終了した時に戻るべきリターンアドレスを書き換えておく。
これにより、関数終了時に別途測定用の関数がコールされることになる。
早速仕組みを実装で追いかけるべく、mipsアーキテクチャを選んで読んで見た。
98 NESTED(_mcount, PT_SIZE, ra) 99 lw t1, function_trace_stop 100 bnez t1, ftrace_stub 101 nop 102 PTR_LA t1, ftrace_stub 103 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 104 bne t1, t2, static_trace 105 nop 106 107 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 108 PTR_L t3, ftrace_graph_return 109 bne t1, t3, ftrace_graph_caller 110 nop 111 PTR_LA t1, ftrace_graph_entry_stub 112 PTR_L t3, ftrace_graph_entry 113 bne t1, t3, ftrace_graph_caller 114 nop 115 #endif 116 b ftrace_stub 117 nop 118 119 static_trace: 120 MCOUNT_SAVE_REGS 121 122 move a0, ra /* arg1: next ip, selfaddr */ 123 jalr t2 /* (1) call *ftrace_trace_function */ 124 move a1, AT /* arg2: the caller's next ip, parent */ 125 126 MCOUNT_RESTORE_REGS 127 .globl ftrace_stub 128 ftrace_stub: 129 RETURN_BACK 130 END(_mcount)
まず、99行、100行目では、トレースが停止されているかどうかを判定する。
測定が測定されている状況なら何もせずreturn。
次に102行、103行目はftrace_trace_functionがftrace_stubと同一かどうかを判断し、同一であれば特に何もせずに抜けている。
ftrace_trace_functionは、kernel/trace/ftrace.cで定義された関数ポインタで、初期値がftrace_stubである。
このことより、ftrace_trace_functionは明示的に何らかの関数が設定されない限り、mcount内で何もしないようになっている。
107行 - 115行目はとりあえず考えないで、120行目から考える。
保存する必要のあるレジスタ値を保存して、第一引数に「呼び出し元の戻りアドレス」、第に引数に「呼び出し元の呼び出し元のアドレス」を渡す様だ。
(mipsでは関数呼び出し時、a0に第一引数を、a1に第二引数を渡す。)
そして、ftrace_trace_functionの指す先にジャンプする。
ここまで見た限り、論文にあるようなスタック弄りはなさそうだ。
ということは、ftrace_trace_functionに設定された関数でやっているということだろうか?