bpftrace 的一些陷阱 🔗
“char[]” 的问题 🔗
举个例子,xfs_lookup 对应 tracepoint 中的第四个参数 name 被声明为 char[] 而不是 char*. 这在 C 里面没有区别,而在 bpftrace 里面却有明显的区别。
$ bpftrace -lv tracepoint:xfs:xfs_lookup
tracepoint:xfs:xfs_lookup
dev_t dev
xfs_ino_t dp_ino
int namelen
__data_loc char[] name
如果 name 并不是 ASCII 字符串,里面其实存放的是字符对应的 16进制值(比如,A 对应的值存放了 0x10 而不是 0x41),则用 %s 输出就会碰到“意外”。这在输出 uuid 的时候特别容易碰到。
bpftrace treats
char *andchar []differently, and the type of former isType::integerand the latter isType::string.
对于 Type::string, 无法用 [] 的形式访问其中的单个字符。
$ bpftrace -e 'BEGIN{ $s = "hello"; printf("%s\n", $s[0]);}'
...
stdin:1:22-43: ERROR: printf: %s specifier expects a value of type string (none supplied)
同时,对于一个 Type::string,也不能用 str() 函数做转换(因为本来就是 string)。
$ bpftrace -e 'BEGIN{ $s = "hello"; printf("%s\n", str($s));}'
stdin:1:37-44: ERROR: str() expects an integer or a pointer type as first argument (string[6] provided)
以上问题可以参考 GitHub issue #1010
‘%r’ raw 输出 🔗
如果 char[] 确实包含非 ASCII 编码,又实在想查看里面的内容,可以试试:
$ bpftrace -e ... '{printf("%r\n", buf(args->uuid, 16));}'
\xa7\xdc\xf3\x1e\xe1\x14\x11\xee\xb0H\xb4\x05]\xad\x1f\
里面除了正常的 \xa7 等等,还会出来 H & ]. 这也是个现有问题,高版本的 bpftrace 可以通过 %rx 来解决,见 GitHub issue #2009.
字符串查找 🔗
高版本的 bpftrace 有新 built-in 函数 strcontains,老版本只能 strncmp.
ustack() 打印的堆栈只有地址没有符号 🔗
那是因为被跟踪的进程先退出了。bpftrace 跟踪结束的时候,保证待跟踪进程还在就行。