简介

重要:是kprobe和tracepoint的替代方案,0开销的机制,并提供故障排除和调试功能。

只要是tracepoint、kprobe的插桩点都可以使用,并且可以直接访问参数中不需要BPF帮助函数进行读取。

一般来说,这三个程序的执行顺序为:fentry、fmodify_return(若返回非0,则可阻止函数执行,需要开启CONFIG_BPF_KPROBE_OVERRIDE)、fexit

SEC("fentry/do_unlinkat")
int BPF_PROG(do_unlinat_entry, int dfd, struct filename *name)
{

}

SEC("fexit/do_unlinkat")
int BPF_PROG(do_unlinat_entry, int dfd, struct filename *name, long ret)
{

}

SEC("fmod_ret/do_unlinkat")
int BPF_PROG(do_unlinat_entry, int dfd, struct filename *name, long ret)
{

}

实现机制

trampolines(蹦床)

在Linux上下文中,该术语表示内存中包含要跳转到的地址位置。

该机制有许多应用:

  • 中断服务例程

  • I/O例程

在这些应用中,当某些时间发生时,执行将跳转到对应的位置。

ftrace

在2.6.27内核开始支持。

Ftrace是内核中用于观察函数执行的一种机制,传统上用于调试目的,也使用蹦床机制,但是方式略微不同。

使用CONFIG_FUNCTION_TRACER编译内核时启用该机制。启用后,大多数文件都使用-pg、-mnop-mcount=...标志进行编译,主要是在函数开头添加一些额外的NOP指令。

因此在程序执行时,CPU可能会遇到一些NOP指令,会直接忽略往后执行;也可以用内核将NOP替换为蹦床,以便跟踪函数。

/* 没有开启ftrace的函数 */
some_kernel_func:
	push xxx
	mov xxx, xxx
	...
	ret

/* 开启ftrace的函数 */
some_kernel_func:
	nop
	nop
	push xxx
	mov xxx, xxx
	...
	ret

/* 跟踪函数 */
some_kernel_func:
	call tarce_func
	nop
	push xxx
	mov xxx, xxx
	...
	ret

BPF 蹦床

BPF 蹦床也是利用蹦床的机制对nop指令进行修改,以达到进入自定义插桩函数的目的,目前支持以下几种情况:

  • 不调用原始程序(freplace)

  • 在原始程序前(fentry)

  • 在原始程序后(fexit)

  • 修改原始程序返回值(fmodify_return)

更多推荐