kprobe
需要内核启用以下配置
config_kprobes=y
config_have_kprobes=y
config_kprobe_event=y
kprobe_events有两种类型:kprobe
,kretprobe
kprobe_evnets规则添加的入口:/sys/kernel/debug/tracing/kprobe_events
- kprobe
在函数调用时进行探测,可以用来判断函数是否被调用以及调用函数的传参值是什么.
用法:
echo "p:probe1 input_event type=%x1 code=%x2 value=%x3" > /sys/kernel/debug/tracing/kprobe_events
kretprobe
在函数调用完成后探测,可以用来判断函数执行的结果.
用法:echo "r:probe2 input_event $retval" > /sys/kernel/debug/tracing/kprobe_events
用法说明:
p
代表kprobe
模式
r
代表kretprobe
模式
probe1
,probe2
为探测点的名称,可以任意命名
input_event
被探测的函数
type
,code
,value
自定义字段
%x1
,%x2
,%x3
arm架构下传参寄存器分别代表探测函数的第2,3,4个参数,用于给自定义字段赋值
$retval
用于kretprobe
模式,代表探测函数的返回值
如果有多个探测点可以将重定向>
替换成追加>>
kprobe模式下如何查看探测函数参数列表中的结构体成员的值
例如:探测函数void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
,获取usage->hid
,usage->type
,usage->code
的值,并根据hid
过滤.
在kernel 4.4.131中:
struct hid_usage {
unsigned hid; /* hid usage code */
unsigned collection_index; /* index into collection array */
unsigned usage_index; /* index into usage array */
/* hidinput data */
__u16 code; /* input driver code */
__u8 type; /* input driver type */
__s8 hat_min; /* hat switch fun */
__s8 hat_max; /* ditto */
__s8 hat_dir; /* ditto */
};
其中hid字段结构体内offset=0
code offset=12
type offset=14
echo "p:probeg6 hidinput_hid_event hid= 0(%x2):u32 type= 14(%x2):u8 code= 12(%x2):u16" >> /sys/kernel/debug/tracing/kprobe_events
echo "hid < 0x700e0 || hid > 0x700e7" > /sys/kernel/debug/tracing/events/kprobes/probeg6/filter
%x2
获取hidinput_hid_event
函数的第3个参数
0(%x2)
对第3个参数进行取值操作
:u32
定义数据类型为u32,如果字段为字符串可定义为string
14(%x2)
先对第3个参数进行取值操作,然后 14个字节的偏移
对探测结果进行条件过滤
echo "p:probe1 input_event type=%x1 code=%x2 value=%x3" > /sys/kernel/debug/tracing/kprobe_events
echo "type == 1" > /sys/kernel/debug/tracing/events/kprobes/probe1/filter
type == 1
仅输出type值为1的条目,在kretprobe
模式下也可以对探测函数的返回值进行过滤.
cat /sys/kernel/debug/tracing/trace_pipe
该操作会阻塞
kprobe输出字段的含义
# tracer: nop
#
# entries-in-buffer/entries-written: 0/0 #p:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# task-pid cpu# |||| timestamp function
# | | | |||| | |
echo "1" > /sys/kernel/debug/tracing/events/kprobes/enable
echo "0" > /sys/kernel/debug/tracing/events/enable
echo "" > /sys/kernel/debug/tracing/kprobe_events