【kernel doc】【trace】kprobetrace翻译

原文链接:
Kprobe-based Event Tracing

概述

这些事件类似于基于tracepoint的事件。 但不同于Tracepoint,它基于 kprobes(kprobe 和 kretprobe)。 因此它可以探测 kprobes 可以探测的任何地方(这意味着,除了带有 __kprobes/nokprobe_inline 注释和标记为 NOKPROBE_SYMBOL 的那些函数之外的所有函数)。
与基于 Tracepoint 的事件不同,它可以动态添加和删除。

要启用此功能,请使用 CONFIG_KPROBE_EVENTS=y 构建内核。

与事件tracer类似,它不需要通过 current_tracer 激活。 取而代之的是,通过添加探测点
/sys/kernel/debug/tracing/kprobe_events,并通过启用它
/sys/kernel/debug/tracing/events/kprobes/<EVENT>/enabled

kprobe_events 的概要

p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : 设置一个probe
r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : 设置一个return probe
-:[GRP/]EVENT : 清除probe

GRP:组名。如果省略,请使用“kprobes”。
EVENT:事件名称。如果省略,则根据 SYM+offs 或 MEMADDR 生成事件名称。
MOD : 给出了 SYM 的模块名称。
SYM[+offs] :插入probe的符号+偏移量。
MEMADDR :probe插入的地址。
MAXACTIVE : 可以同时探测的指定函数的最大实例数,或 0 作为默认值,如文档/kprobes.txt 部分 1.3.1 中所定义。

FETCHARGS :参数。每个探针最多可以有 128 个参数。

 %REG : 获取寄存器 REG
 @ADDR :在 ADDR 处获取内存(ADDR 应该在内核中)
 @SYM[+|-offs] :在 SYM +|- offs 处获取内存(SYM 应该是数据符号)
 $stackN : 获取栈的第 N 个条目 (N >= 0)
 $stack :获取堆栈地址。
 $retval : 获取返回值。(*)
 $comm :获取当前任务comm。
 +|-offs(FETCHARG) : 在 FETCHARG +|- offs 地址获取内存。(**)
 NAME=FETCHARG :将 NAME 设置为 FETCHARG 的参数名称。
 FETCHARG:TYPE : 将 TYPE 设置为 FETCHARG 的类型。目前,基本类型(u8/u16/u32/u64/s8/s16/s32/s64),十六进制类型(x8/x16/x32/x64),支持“字符串”和位域。
 (*) 只针对return probe
 (**) 对于获取数据结构的域很有用处

Type

fetch-args 支持多种类型。 Kprobe tracer将按给定类型访问内存。 前缀 ‘s’ 和 ‘u’ 表示这些类型分别是有符号和无符号的。 ‘x’ 前缀意味着它是无符号的。 被trace的参数以十进制(“s”和“u”)或十六进制(“x”)显示。 如果没有类型转换,使用 ‘x32’ 或 ‘x64’ 取决于架构(例如 x86-32 使用 x32,而 x86-64 使用 x64)。
字符串类型是一种特殊类型,它从内核空间获取一个“以空字符结尾的”字符串。 这意味着如果字符串容器已被调出,它将失败并存储 NULL。
位域是另一种特殊类型,它采用 3 个参数,位宽、位偏移和容器大小(通常为 32)。 语法是;

b<bit-width>@<bit-offset>/<container-size>

对于 $comm,默认类型是 “string”; 任何其他类型都是无效的。

Per-Probe Event Filtering

Per-probe事件过滤功能允许您在每个probe上设置不同的过滤器,并向你提供参数,此参数也将在跟踪缓冲区中显示。 如果在 kprobe_events 中的 ‘p:’ 或 ‘r:’ 之后指定了正确的名称,则会在tracing/events/kprobes/<EVENT> 下添加一个事件,在目录中您可以看到 ‘id’, ‘enabled’, ’ 格式”和“过滤器”。

enabled:
您可以通过在其上写入 1 或 0 来启用/禁用探针。

format:
这显示了此探测事件的格式。

filter:
您可以编写此事件的过滤规则。

ID:
这显示了此探测事件的 ID。

Event Profiling

您可以通过以下方式检查probe命中总数和probe未命中总数
/sys/kernel/debug/tracing/kprobe_profile
第一列是事件名称,第二列是探测命中数,第三列是探测未命中数。

Usage examples

要将探测器添加为新事件,请向 kprobe_events 写入新定义
如下。

   echo 'p:myprobe do_sys_open dfd=%ax filename=%dx flags=%cx mode=+4($stack)' \
   > /sys/kernel/debug/tracing/kprobe_events
   (译注:这里的ax dx cx 都是寄存器名字)

这会在 do_sys_open() 函数的顶部设置一个 kprobe,将第 1 到第 4 个参数记录为“myprobe”事件。 请注意,分配给每个函数参数的寄存器/堆栈条目取决于特定于架构的 ABI。 如果您不确定 ABI,请尝试使用 perf-tools 的 probe 子命令(您可以在 tools/perf/ 下找到它)。
如本示例所示,用户可以为每个参数选择更熟悉的名称。

   echo 'r:myretprobe do_sys_open $retval' >> /sys/kernel/debug/tracing/kprobe_events

这会在 do_sys_open() 函数的返回点设置一个 kretprobe,并将返回值记录为“myretprobe”事件。
您可以通过以下方式查看这些事件的格式 /sys/kernel/debug/tracing/events/kprobes/<EVENT>/format.

cat /sys/kernel/debug/tracing/events/kprobes/myprobe/format
name: myprobe
ID: 780
format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3; size:1;signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;

        field:unsigned long __probe_ip; offset:12;      size:4; signed:0;
        field:int __probe_nargs;        offset:16;      size:4; signed:1;
        field:unsigned long dfd;        offset:20;      size:4; signed:0;
        field:unsigned long filename;   offset:24;      size:4; signed:0;
        field:unsigned long flags;      offset:28;      size:4; signed:0;
        field:unsigned long mode;       offset:32;      size:4; signed:0;
     
print fmt: "(%lx) dfd=%lx filename=%lx flags=%lx mode=%lx", REC->__probe_ip,
REC->dfd, REC->filename, REC->flags, REC->mode

您可以看到事件有 4 个参数,如您指定的表达式。

echo > /sys/kernel/debug/tracing/kprobe_events

这将清除所有探测点。

或者,

echo -:myprobe >> kprobe_events

这将选择性地清除探测点。
在定义之后,默认情况下每个事件都是禁用的。 要跟踪这些事件,您需要启用它。

   echo  1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
   echo 1 > /sys/kernel/debug/tracing/events/kprobes/myretprobe/enable

您可以通过 /sys/kernel/debug/tracing/trace 查看跟踪信息。

  cat /sys/kernel/debug/tracing/trace
# tracer: nop
#
#           TASK-PID    CPU#    TIMESTAMP  FUNCTION
#              | |       |          |         |
           <...>-1447  [001] 1038282.286875: myprobe: (do_sys_open+0x0/0xd6) dfd=3 filename=7fffd1ec4440 flags=8000 mode=0
           <...>-1447  [001] 1038282.286878: myretprobe: (sys_openat+0xc/0xe <- do_sys_open) $retval=fffffffffffffffe
           <...>-1447  [001] 1038282.286885: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=40413c flags=8000 mode=1b6
           <...>-1447  [001] 1038282.286915: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $retval=3
           <...>-1447  [001] 1038282.286969: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=4041c6 flags=98800 mode=10
           <...>-1447  [001] 1038282.286976: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $retval=3

每行显示内核何时触发事件,<- SYMBOL 表示内核从 SYMBOL 返回(例如“sys_open+0x1b/0x1d <- do_sys_open”表示内核从 do_sys_open 返回到 sys_open+0x1b)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值