静态ftrace
- 性能工具
- 2024-08-29
- 168热度
- 0评论
上面章节主要描述的是动态ftrace,在早期还有静态ftrace。区别主要如下:
- 动态ftrace与静态ftrace在编译参数方面静态编译使用的是参数“-pg”,而动态使用的是fpatchable-function-entry。
- 工具链使能“-pg”参数时,会在每个函数体前面插入_mcount函数。而动态ftrace会在函数入口(函数准备阶段前)插入nop指令。
- 静态ftrace插入的_mcout直到代码运行期间一直存在,而动态ftrace在不使能tracer是nop指令,动态ftrace可以动态的修改代码。
内核编译时,使能CONFIG_FUNCTION_TRACER时会启动该参数编译,在kernel目录下的Makefile可以看到。
# The arch Makefiles can override CC_FLAGS_FTRACE. We may also append it later.
ifdef CONFIG_FUNCTION_TRACER
CC_FLAGS_FTRACE := -pg
endif
基本原理
void ftrace_stub(void)
{
return;
}
void mcount(void)
{
/* save any bare state needed in order to do initial checking */
extern void (*ftrace_trace_function)(unsigned long, unsigned long);
if (ftrace_trace_function != ftrace_stub)
goto do_trace;
① 如果用户定义了trace函数,那么就跳转到do_trace,执行ftrace_trace_function。否则什么都不做,直接返回。
/* restore any bare state */
return;
do_trace:
/* save all state needed by the ABI (see paragraph above) */
unsigned long frompc = ...;
unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
ftrace_trace_function(frompc, selfpc);
② 跳转执行ftrace_trace_function
/* restore all state needed by the ABI */
}
编译完成插桩点
通过反汇编objdump -D vmlinux > log后查看_mcount被插入到了vfs_read中,插入的位置在函数准备阶段之后,函数体内容之前。系统运行时,可以使用gdb 查看汇编指令,与上面基本一致。
我们接着再查看以下_mcount的实现,如下