kprobe_events shell模式使用教學

2023-06-01 21:01:15

kprobe_events shell模式使用教學

使用前提

需要核心啟用以下設定
CONFIG_KPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_KPROBE_EVENT=y

kprobe_events

kprobe_events有兩種型別:kprobe,kretprobe
kprobe_evnets規則新增的入口:/sys/kernel/debug/tracing/kprobe_events

  1. kprobe
    在函數呼叫時進行探測,可以用來判斷函數是否被呼叫以及呼叫函數的傳參值是什麼.
    用法:
    echo "p:probe1 input_event type=%x1 code=%x2 value=%x3" > /sys/kernel/debug/tracing/kprobe_events
  2. 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,%x3ARM架構下傳參暫存器分別代表探測函數的第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個位元組的偏移

filter

對探測結果進行條件過濾

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
#              | |       |   ||||       |         |

啟動kprobe

echo "1" > /sys/kernel/debug/tracing/events/kprobes/enable

關閉kprobe

echo "0" > /sys/kernel/debug/tracing/events/enable
echo "" > /sys/kernel/debug/tracing/kprobe_events