0

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

我是 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数量?脚本有什么问题吗?

4

1 回答 1

0

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

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

pid 提供者当然可以公开函数参数,但是除非 FreeBSD 的 DTrace 支持用户级 CTF,否则它们的类型将不可用。这可能就是您发现 typedargs[n]不可用并且您被限制为 integer 的原因argn

我猜该函数get_system_info()填充struct system_info. 如果是这种情况,那么您必须在从函数返回后复制结构。此外,如果 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) 为它看到的各种类型使用适当的大小。

于 2013-08-17T01:44:42.397 回答