如何让 perf 脚本将字符串参数显示为文本而不是指针值?

Posted

技术标签:

【中文标题】如何让 perf 脚本将字符串参数显示为文本而不是指针值?【英文标题】:How to get perf script to show string args to system calls as text, not pointer values? 【发布时间】:2021-03-29 09:17:35 【问题描述】:

我正在尝试使用 perf 跟踪已删除的文件。我知道 eBPF / SystemTap 更适合这里,但我在工具选择(ARM)的平台上受到限制。

我就是这样记录的

perf record -e 'syscalls:sys_enter_unlinkat'

用于报告

perf script -F +pid,+tid,-cpu
rm 15746/15746  7942.646974: syscalls:sys_enter_unlinkat: dfd: 0xffffff9c, pathname: 0x55a7960e6490, flag: 0x00000000
rm 15748/15748  7944.626120: syscalls:sys_enter_unlinkat: dfd: 0xffffff9c, pathname: 0x55dea122f490, flag: 0x00000000
rm 15750/15750  7947.111921: syscalls:sys_enter_unlinkat: dfd: 0xffffff9c, pathname: 0x55a515165490, flag: 0x00000000

如何获得类似于 strace 输出的 pathname 的字符串版本。 我还需要删除文件的进程的uid。

【问题讨论】:

这是一个关于 Linux 实用程序的问题,与代码、编程或软件开发无关。因此,这不是一个 SO 问题。 @Clifford:对我来说似乎还可以; perf script 基本上是一种脚本语言,我认为。 (而且,虽然这些因素单独不够用,但通常只有嵌入式开发人员会以这种方式使用此工具;在普通系统上,您只需使用strace。我并不是说嵌入式开发人员所做的一切都会自动成为 SO 问题,但由于有充分的理由将其视为编程问题,这也是让它留在 SO 上而不是迁移到超级用户的理由。成为话题。) @PeterCordes :好的 - 反对撤回。 【参考方案1】:

在这种情况下,使用perf 工具将无法获取pathname 的字符串版本。

当用户空间实用程序调用perf_even_open syscall 并请求监视跟踪点事件时,例如您尝试使用syscalls:sys_enter_unlinkat 监视的事件,“性能探测”功能会附加到跟踪点。可以看到探测函数here。

探测函数分配perf buffer 和validates 分配的缓冲区,然后调用bpf 程序。

这个 bpf 程序需要知道静态跟踪点事件的“格式”,因为它需要了解 perf 环形缓冲区中二进制跟踪输出的结构。

事件的格式在 /sys/kernel/debug/tracing/events/syscalls/sys_enter_unlinkat/format 文件中定义,适合您的情况。

如果您查看此文件,您将看到 perf script 根据字段中的 print fmt 条目报告输出。

name: sys_enter_unlinkat
ID: 722
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:int __syscall_nr; offset:8;       size:4; signed:1;
        field:int dfd;  offset:16;      size:8; signed:0;
        field:const char * pathname;    offset:24;      size:8; signed:0;
        field:int flag; offset:32;      size:8; signed:0;

print fmt: "dfd: 0x%08lx, pathname: 0x%08lx, flag: 0x%08lx", ((unsigned long)(REC->dfd)), ((unsigned long)(REC->pathname)), ((unsigned long)(REC->flag))

perf 用户空间实用程序将始终遵循这种格式,并且不会偏离它。你可以从thiscommit 看到一些细节。

如果不对内核跟踪点 API 进行真正广泛的修改,我看不到使用 perf 实现您想要的方法。

如果您只想跟踪文件删除活动,并且想了解有关它的更多详细信息,我建议您尝试查看fanotify。

【讨论】:

感谢 fanotify 绝对值得一看。但是我换了ply。它是 eBPF 的一个非常小的包装器。据报道它非常有问题,但在这种情况下对我来说效果很好。

以上是关于如何让 perf 脚本将字符串参数显示为文本而不是指针值?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法让 XmlReader 将字符引用保留为文本而不是转换它?

将 HTML 编码的字符串附加为 HTML,而不是文本

如何让Access 空文本框参与计算时默认是0,如图碳粉为空,计算时自动变0,别用VB代码,VB我会,请用VBA

如何从 HTML TextNode 而不是 HTML 标记中获取实际显示的文本?

Google Chrome 将 json AJAX 响应显示为树而不是纯文本,新版本

脚本在我的字符 LCD 上显示 Unicode