uprobe是用户态的探针,它和kprobe是相对应的,kprobe是内核态的探针。uprobe需要制定用户态探针在执行文件中的位置,插入探针的原理和kprobe类似。
参考原文:Uprobe-tracer: Uprobe-based Event Tracing
1、Overview
uprobe event类似于kprobe event。在编译内核时配置CONFIG_UPROBE_EVENTS=y使能这个特性。
它的active不是通过current_tracer接口,而是通过“/sys/kernel/debug/tracing/uprobe_events”来增加probe points,通过“/sys/kernel/debug/tracing/events/uprobes/
然而和kprobe event不同,uprobe event期望用户计算probepoint在目标中的偏移。
2、Synopsis of uprobe_tracer
增加/删除event的命令格式:
1 | p[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a uprobe |
2.1、Types
在”fetch-args”中支持一系列的types,Kprobe tracer能够使用给定的type来存取内存。
- ‘s’ 、‘u’前缀:分别表明signed、unsigned;
- ‘x’前缀:意味着unsigned;
- 数字:十进制(‘s’ and ‘u’) ,16进制(‘x’)。没有类型固定,数字使用‘x32’还是‘x64’取决于架构(x86-32 uses x32, and x86-64 uses x64);
- 字符串:将会在内存中读取一个“null-terminated”的字符串。
Bitfield:有3个参数bit-width, bit- offset, container-size (usually 32).
1
b<bit-width>@<bit-offset>/<container-size>
对“$comm”,默认是“string”类型,其他类型非法。
3、Event Profiling
你可以通过/sys/kernel/debug/tracing/uprobe_profile查看所有kprobe event的命中和miss情况。第一列是event name,第二列是probe hits计数,第三列是probe miss-hits计数。
4、Usage examples
增加一个新的uprobe event,命令如下(在可执行文件/bin/bash的0x4245c0偏移处增加一个uprobe探针):
1
echo 'p /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
增加一个uretprobe event:
1
echo 'r /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
删除一个已注册的event:
1
echo '-:p_bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
打印出所有已注册的events:
1
cat /sys/kernel/debug/tracing/uprobe_events
清除掉所有的events:
1
echo > /sys/kernel/debug/tracing/uprobe_events
以下的例子展示怎么找到probe位置的地址,dump其instruction pointer 和 %ax register,探测/bin/zsh中的zfree函数:
1 | # cd /sys/kernel/debug/tracing/ |
0x46420是zfree在/bin/zsh中的偏移,/bin/zsh的内存加载地址为0x00400000。因此命令为:
1 | # echo 'p:zfree_entry /bin/zsh:0x46420 %ip %ax' > uprobe_events |
同样的uretprobe为:
1 | # echo 'r:zfree_exit /bin/zsh:0x46420 %ip %ax' >> uprobe_events |
注意:用户必须明确的计算对象中的探测点的偏移量
我们可以看到已经注册的events:
1 | # cat uprobe_events |
可以从 events/uprobes/zfree_entry/format中查看event的输出格式:
1 | # cat events/uprobes/zfree_entry/format |
定义以后,使能所有的events:
1 | # echo 1 > events/uprobes/enable |
sleep以后,disable events:
1 | # sleep 20 |
还可以通过/sys/kernel/debug/tracing/trace文件查看trace信息:
1 | # cat trace |
输出显示给我们uprobe被触发时:pid 24842、ip 0x446420、ax register 79,uretprobe被触发时:ip at 0x446540从函数入口0x446420返回。