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に設定された関数でやっているということだろうか?