由于DTrace probe
在操作系统的kernel
空间执行,所以不能直接访问进程user space
的内容。通常要使用copyin
、copyinstr
这些函数把进程user space
的内容copy
出来。如果程序里的变量是个二级指针,就要相对麻烦一些。以下面程序为例(编译成32
位的程序,所以指针用uint32_t
):
#include <stdio.h>
void func(char **p)
{
*p = strdup("hello");
return;
}
int main(void)
{
char *p = NULL;
func(&p);
printf("%s\n", p);
return 0;
}
如果要在func
函数返回时,打印p
指针指向的字符串值。可以使用以下脚本:
#!/usr/sbin/dtrace -qs
pid$target::func:entry
{
self->s = arg0;
}
pid$target::func:return
{
this->s = (uint32_t*)copyin(self->s, sizeof(uint32_t));
printf("%s\n",copyinstr(*(this->s)));
}
首先,在pid$target::func:entry
这个probe
里,记录下p
的值。
接下来,在pid$target::func:return
这个probe
里,第一次copyin
操作把*p
的值copy
到this->s
所指向的kernel
内存里,*(this->s)
则为*p
的值,由于这个值所指向的地址依然是user space
的地址,所以要打印这个字符串,还要用一次copyinstr
。
执行脚本,运行结果如下:
-bash-3.2# ./debug.d -c ./a
hello
hello
可以看到一个“hello
”是程序打印出来的,另一个是脚本打印出来的。