gcc的-pg选项
ftrace 支持动态trace,即可以跟踪内核和模块中任意的全局函数。它利用了gcc的-pg编译选项,在每个函数的开始增加一个stub,这样在需要的时候可以控制函数跳转到指定的代码中去执行。用过gprof工具应该对gcc的-pg选项不陌生了。
当CONFIG_FUNCTION_TRACER打开时,编译时会增加-pg编译选项,gcc会在每个函数的入口处增加对mcount的调用。
gcc 4.6新增加了-pg -mfentry支持,这样可以在函数的最开始插入一条调用fentry的指令。
通过nm可以看到多了一个未定义的符号fentry
对于动态ftrace,有一个很重要的工作就是记录这些被-pg影响的函数,最终可以通过读debugfs的文件/sys/kernel/debug/tracing/available_filter_functions来查看哪些函数是支持trace的。
编译内核
内核在编译代码时,先指定-pg -fentry选项编译生成.o文件,然后通过scripts/recordmcount.pl脚本来处理.o文件
以一个简单的foo.c文件举例
经过scripts/recordmcount.pl处理之后,.o文件中新增了一个__mcount_loc段,在最终链接时被重定向,里面记录了所有插入了mcount或者fentry的函数地址。
最终内核的链接脚本include/asm-generic/vmlinux.lds.h将__mcount_loc段的内容放在.init.data段中,并且通过__start_mcount_loc和__stop_mcount_loc两个全局符号来访问。
ftrace初始化
gcc的-pg -mfentry选项在每个函数开始处增加了一条callq指令,它和对应的retq据统计会带来13%的性能开销,因此在内核的初始化阶段将这些callq指令全部修改为5 Byte的NOP指令: 66 66 66 66 90H,同时将这些指令的地址记录下来。
scripts/recordmcount.pl过滤了kernel/trace/ftrace.o,没有为其增加__mcount_loc段,所以ftrace代码不会修改其自身的代码。
ftrace_init在start_kernel中调用,
gcc的-pg选项
最新推荐文章于 2025-06-29 13:51:36 发布