Kprobes events

写一个包含 Kprobes 注册/注销的模块稍微有点复杂, 使用 Kprobes events 就像对简单一些. 它们类似基于 tracepoint 的events, 但是使用 Kprobes 实现的, 可以动态的添加删除.

概念

  1. 要使用此功能, 编译 Kernel的时候, 必须 CONFIG_KPROBE_EVENTS=y.;
  2. 类似其它 event tracer, 不需要通过 current_tracer 激活;
  3. 通过 /sys/kernel/tracing/kprobe_events/sys/kernel/tracing/dynamic_events 添加 Kprobes events;
  4. 通过 /sys/kernel/tracing/events/kprobes/<EVENT>/enable 开启 events;
  5. /sys/kernel/tracing/kprobe_profile 统计 hit 多少, miss 多少.

一个简单的例子

下面的例子使用探测 uptime_proc_show 函数, 建立以 trace_sample 为event 名字的 Kprobes event.

可以看到动态添加这个 Kprobes events 之后, 对应的文件夹被建立了.

并且不需要设置 current_tracer.

# 保证环境正确
$ echo 0 > /sys/kernel/tracing/tracing_on
$ echo "" > /sys/kernel/tracing/trace

# 设置 Kprobes events
$ echo "p:trace_sample uptime_proc_show" > /sys/kernel/debug/tracing/kprobe_events

# 查看新生成的 Kprobes 文件夹
$ ls /sys/kernel/tracing/events/kprobes/trace_sample/
enable  filter  format  hist  id  inject  trigger

$ echo 1 > /sys/kernel/tracing/events/kprobes/trace_sample/enable

# 开启 probe 
$ echo 1 > /sys/kernel/tracing/tracing_on

# 执行包含该函数的命令
$ uptime

# 查看结果
$ cat /sys/kernel/tracing/trace
# tracer: nop
#
# entries-in-buffer/entries-written: 1/1   #P:8
#
#                                _-----=> irqs-off
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| / _-=> migrate-disable
#                              |||| /     delay
#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION
#              | |         |   |||||     |         |
          uptime-40063   [007] ..... 67233.823241: trace_sample: (uptime_proc_show+0x0/0x1d0)

# 清理
$ echo 0 > /sys/kernel/tracing/tracing_on
$ echo 0 > /sys/kernel/tracing/events/kprobes/trace_sample/enable
$ echo -:trace_sample > /sys/kernel/debug/tracing/kprobe_events

查看 ksys_read 系统调用返回值的例子

下面的内容都放到 test.sh 文件里, 然后执行 sh test.sh

echo $$

# 准备
echo 0 > /sys/kernel/tracing/tracing_on
echo "" > /sys/kernel/tracing/trace

# 注册事件
echo "r:myreturnprobe ksys_read $retval" > /sys/kernel/debug/tracing/kprobe_events
echo $$ > /sys/kernel/debug/tracing/set_event_pid

#开启
echo 1 > /sys/kernel/tracing/events/kprobes/myreturnprobe/enable
echo 1 > /sys/kernel/tracing/tracing_on

# 等一会, 然后查看结果, 命令替换同一个进程读
sleep 5
output=$(cat /tmp/test.sh > /dev/null)

# 关闭
echo 0 > /sys/kernel/tracing/tracing_on

# 查看结果
cat /sys/kernel/tracing/trace

# 清理
echo 0 > /sys/kernel/tracing/events/kprobes/myreturnprobe/enable
echo -:myreturnprobe > /sys/kernel/debug/tracing/kprobe_events 2>/dev/null

echo "done"

Kprobes events 格式

更多说明在这里: https://docs.kernel.org/trace/kprobetrace.html

 p[:[GRP/][EVENT]] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS]        : Set a probe
 r[MAXACTIVE][:[GRP/][EVENT]] [MOD:]SYM[+0] [FETCHARGS]        : Set a return probe
 p[:[GRP/][EVENT]] [MOD:]SYM[+0]%return [FETCHARGS]            : Set a return probe
 -:[GRP/][EVENT]                                               : Clear a probe

参考:
https://docs.kernel.org/trace/kprobetrace.html

标签: none

添加新评论