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

时间:2013-08-16 23:58:11

标签: freebsd dtrace

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

我是DTrace'ing“顶级”实用程序,(“顶级”实用程序都有 在目标文件中构建的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] 

假设显示cpus的数量?脚本有什么问题吗?

1 个答案:

答案 0 :(得分:0)

我曾经在9.1和9.2-RC2上调查过这个问题,但我无法让DTrace正常工作,所以我的评论基于Solaris版本,这应该大致相当。

fbt提供者仪器内核函数。它的用户土地等价物是pid提供者。

pid提供程序当然可以公开函数参数,但是,除非FreeBSD的DTrace支持用户区CTF,否则它们的类型将不可用。这可能是您发现键入的args[n]不可用而且您被限制为整数argn的原因。

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

struct system_info {
    ...
    unsigned int ncpus;
    ...
};

pid$target::get_system_info:entry
{
    self->siup = (uintptr_t)arg0;       /* user-land pointer */
}

pid$target::get_system_info:return
/self->siup/
{
    this->sikp = (struct system_info *) /* kernel pointer */
        copyin(self->siup, sizeof (struct system_info));
    printf("ncpus = %d\n", this->sikp->ncpus);
    self->siup = 0;             /* free thread-local storage */
}

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