FreeBSD 用户空间 DTrace 和用户空间的转储函数参数

Posted

技术标签:

【中文标题】FreeBSD 用户空间 DTrace 和用户空间的转储函数参数【英文标题】:FreeBSD User Space DTrace and dumping function arguments for user space 【发布时间】:2013-08-16 23:58:10 【问题描述】:

我们可以像函数一样为用户空间函数转储函数参数吗 在内核空间?如果我们可以 FBT 提供者转储用户空间函数的参数 执行 dtrace -l -f -v?

我在 DTrace 中使用“top”实用程序,(“top”实用程序同时具有 目标文件中内置的 CTF 和 Dwarf 调试部分)

我正在尝试检查“top”调用的 get_system_info 函数,我 确认它存在待探测

root% dtrace -l | grep get_system_info 
55154  pid8488      top        get_system_info entry 

但我无法将参数转储到函数中......

root% dtrace -l -f get_system_info -v 
   ID   PROVIDER            MODULE                          FUNCTION NAME 
55154    pid8488               top                   get_system_info entry 

        Probe Description Attributes 
                Identifier Names: Private 
                Data Semantics:   Private 
                Dependency Class: Unknown 

        Argument Attributes 
                Identifier Names: Private 
                Data Semantics:   Private 
                Dependency Class: Unknown 

        Argument Types 
                None 

使用简单的脚本进行测试,

pid8488::get_system_info:entry
 
    this->info = (struct system_info *)copyin(args[0], sizeof(struct system_info)); 

...如果我使用 args[0] 表示法,它会显示以下内容,

dtrace: failed to compile script top_d.d: line 17: index 0 is out of 
range for pid8488::get_system_info:entry args[ ]

如果我用 arg0 替换,它会编译但值不是 一定是理智的。 示例 struct system_info 的 ncpus 成员显示垃圾值。

完整的脚本是

pid8488::get_system_info:entry

    this->info = (struct system_info *)copyin(arg0, sizeof(struct system_info));
    printf("last pid [%d] \n", this->info->last_pid);

pid8488::get_process_info:entry

    this->info = (struct system_info *)copyin(arg0, sizeof(struct system_info)); 
    printf("ncpus [%d] \n", this->info->ncpus); 

运行这个

55154         get_system_info:entry last pid [8513] 
55155         get_process_info:entry ncpus [134558720] 

应该显示cpu数量?脚本有什么问题吗?

【问题讨论】:

【参考方案1】:

我曾尝试在 9.1 和 9.2-RC2 上对此进行调查,但我无法让 DTrace 在任何一个上正常工作,因此我的 cmets 基于 Solaris 版本,应该大致相同。

fbt 提供程序检测内核功能。它的用户空间等价物是 pid 提供者。

pid 提供者当然可以公开函数参数,但除非 FreeBSD 的 DTrace 支持用户级 CTF,否则它们的类型将不可用。这可能就是为什么您发现输入的 args[n] 不可用,而您只能使用整数 argn

我猜测函数 get_system_info() 填充了 struct system_info。如果是这种情况,那么您必须在从函数返回的 after 结构中复制。 此外,如果 dtrace(1) 找不到该结构的定义,那么您必须自己提供它,包括它或适当的头文件(并使用 -C 标志)。 这是一个(未经测试的)示例:

结构系统信息 ... 无符号整数 ncpus; ... ; pid$target::get_system_info:entry self->siup = (uintptr_t)arg0; /* 用户域指针 */ pid$target::get_system_info:return /self->siup/ this->sikp = (struct system_info *) /* 内核指针 */ copyin(self->siup, sizeof (struct system_info)); printf("ncpus = %d\n", this->sikp->ncpus); 自我->siup = 0; /* 空闲线程本地存储 */

最后,在评估数据类型(例如指针大小)时,dtrace(1) 将 默认为运行内核的数据模型。如果您正在运行 64 位内核,但您正在检测 32 位进程,则使用“-32”标志,以便 dtrace(1) 对其看到的各种类型使用适当的大小。

【讨论】:

以上是关于FreeBSD 用户空间 DTrace 和用户空间的转储函数参数的主要内容,如果未能解决你的问题,请参考以下文章

FreeBSD打开DTrace支持

用 C 编写一个 DTrace 消费者

为啥 malloc 不能在 FreeBSD-x64 内核空间分配大内存?

在 FreeBSD 中实现 ioctl() 命令

从 DTrace 脚本调用 C 函数

Erlang虚拟机基础设施dtrace探测点介绍和使用