我想知道如何使用 bpftrace 工具来探测内核函数中的局部变量,例如:
int fun1(arg0, arg1, arg2)
{
....
ret1 = arg0->param1;
var1 = xxxx;
.... ;
}
bpftrace 可以探测 arg0、arg1 和 arg2 的数据
但是如何探测var1的变量数据。
我只是在看同样的事情,所以为了后代...... Bpftrace 本身还不能做到这一点。
BTF 中对此没有足够的信息,但如果您有调试信息,您可以根据 perf 发现的内容使用 perf 或 bpftrace。如果添加了支持,则可以让 bpftrace 直接使用 DWARF,但目前还没有。
这个答案基于以下评论:https://github.com/bpftrace/bpftrace/issues/1901#issuecomment-881855742
举一个具体的例子,采用任意内核函数(对于模块性能需要
-m module
),我们可以得到用于截断的newattrs.ia_valid(这是我发现的第一个函数):
[root@c9 ~]# perf probe -L do_truncate
<do_truncate@/usr/src/debug/kernel-5.14.0-284.30.1.el9_2/linux-5.14.0-284.30.1.el9_2.x86_64/fs/open.c:0>
0 int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
loff_t length, unsigned int time_attrs, struct file *filp)
{
3 int ret;
struct iattr newattrs;
/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
if (length < 0)
return -EINVAL;
10 newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
12 if (filp) {
13 newattrs.ia_file = filp;
14 newattrs.ia_valid |= ATTR_FILE;
}
/* Remove suid, sgid, and file capabilities on truncate too */
18 ret = dentry_needs_remove_privs(dentry);
19 if (ret < 0)
return ret;
21 if (ret)
22 newattrs.ia_valid |= ret | ATTR_FORCE;
24 inode_lock(dentry->d_inode);
/* Note any delegations or leases have already been broken: */
26 ret = notify_change(mnt_userns, dentry, &newattrs, NULL);
27 inode_unlock(dentry->d_inode);
28 return ret;
}
long vfs_truncate(const struct path *path, loff_t length)
[root@c9 ~]# perf probe -V do_truncate:26
Available variables at do_truncate:26
@<do_truncate+109>
struct dentry* dentry
struct iattr newattrs
struct user_namespace* mnt_userns
[root@c9 ~]# > dummy
[root@c9 ~]# perf probe do_truncate:26 newattrs.ia_valid
[root@c9 ~]# perf record -e probe:do_truncate_L26 sh -c '> dummy'
[ perf record: Woken up 1 times to write data ]
perf record: Captured and wrote 0.014 MB perf.data (1 samples) ]
[root@c9 ~]# perf script
sh 48158 [003] 41990.971339: probe:do_truncate_L26: (ffffffffae5c250d) ia_valid=0xa068
[root@c9 ~]# perf probe --dry-run -v do_truncate:26 newattrs.ia_valid
...
Probe point found: do_truncate+109
...
Writing event: p:probe/do_truncate_L26 _text+3941645 ia_valid=+0(%sp):x32
# a 32 bits hex value (x32) at offset 0 above %sp
[root@c9 ~]# bpftrace -e 'kprobe:do_truncate+109 {
printf("Got %x\n", *(int32*)reg("sp"));
}'
Attaching 1 probe...
Got a068