bpftrace 小贴士
比方说我想看 nf_log_buf_close 的调用参数,首先看参数类型
$ s bpftrace -lv kfunc:vmlinux:nf_log_buf_close
kfunc:vmlinux:nf_log_buf_close
struct nf_log_buf * m
然后检查检查类型定义
$ pahole -C nf_log_buf
struct nf_log_buf {
unsigned int count; /* 0 4 */
char buf[1020]; /* 4 1020 */
/* size: 1024, cachelines: 16, members: 2 */
};
然后写 bpftrace
bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {printf("%s\n", str(args->m->buf));}'
可惜上面那个会报错,说 str() 要指针但是传入的是 char[]。
这就是大家经常遇到的 bpftrace 类型问题,非常弱智,但如果你不了解他的运作模式会卡住,放弃。
我的解法是直接从结构体取成员退化成手动偏移:
s bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {$m=(uint8*)args->m; printf("%s\n", str($m+4));}'
这一套方式虽然原始,失去了一些便捷性,但是扩展了边界,用熟练了之后也很快。
比如接下来我就可以稍加修改,只在 nat POSTROUTING 的时候打印栈
$ s bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {$m=(uint8*)args->m; $buf=str($m+4); if (strcontains($buf, "nat/POSTROUTING")) {printf("%s\n", kstack)}}'
这不比 bcc 之流方便太多了。
比方说我想看 nf_log_buf_close 的调用参数,首先看参数类型
$ s bpftrace -lv kfunc:vmlinux:nf_log_buf_close
kfunc:vmlinux:nf_log_buf_close
struct nf_log_buf * m
然后检查检查类型定义
$ pahole -C nf_log_buf
struct nf_log_buf {
unsigned int count; /* 0 4 */
char buf[1020]; /* 4 1020 */
/* size: 1024, cachelines: 16, members: 2 */
};
然后写 bpftrace
bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {printf("%s\n", str(args->m->buf));}'
可惜上面那个会报错,说 str() 要指针但是传入的是 char[]。
这就是大家经常遇到的 bpftrace 类型问题,非常弱智,但如果你不了解他的运作模式会卡住,放弃。
我的解法是直接从结构体取成员退化成手动偏移:
s bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {$m=(uint8*)args->m; printf("%s\n", str($m+4));}'
这一套方式虽然原始,失去了一些便捷性,但是扩展了边界,用熟练了之后也很快。
比如接下来我就可以稍加修改,只在 nat POSTROUTING 的时候打印栈
$ s bpftrace -e 'kfunc:vmlinux:nf_log_buf_close {$m=(uint8*)args->m; $buf=str($m+4); if (strcontains($buf, "nat/POSTROUTING")) {printf("%s\n", kstack)}}'
这不比 bcc 之流方便太多了。