是否有可能在dtrace中获得objc方法的结果?

时间:2011-08-12 22:44:37

标签: objective-c dtrace

我编写了一个在任何objc方法返回时触发的动作(objc ::: return)。 现在,我需要获得返回值。有可能吗?

1 个答案:

答案 0 :(得分:5)

总结:不,您无法在DTrace探测中获取Objective-C方法的返回值。

Bill Bumgarner有一个post on tracing messages to nil,其中他说:

  

除此之外:此时无法通过dtrace跟踪objc_msgSend()的返回。鉴于函数实际上没有返回,这并不奇怪 - 就dtrace而言,它只不过是序言。

博客文章相当陈旧(2008年1月),它使用pid提供程序,而不是objc提供程序。也就是说,从Mac OS X v10.7.1开始它仍然有效,它也适用于objc提供商。

有趣的是,它似乎有时会起作用,但这取决于DTrace何时读取RAX寄存器。由于objc_msgSend()未返回,因此DTrace最终使用RAX中已由代码存储的值,这些值不一定是被跟踪方法的返回值。

请考虑以下代码:

NSNumber *n = [NSNumber numberWithInt:1234];
printf("n has address %p\n", n);

以及以下探测:

objc$target:NSPlaceholderNumber:-initWithInt?:return
{
    printf("Returning from -[NSPlaceholderNumber initWithInt:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

使用DTrace运行时,我得到以下输出:

n has address 0x4d283
Returning from -[NSPlaceholderNumber initWithInt:]
    return value = 0x4d283

因此,探测器似乎能够捕获-initWithInt:的返回值。这只是运气,可能是由CFNumberCreate()调用的函数(例如CFMakeCollectable()-initWithInt:)引起的,最终将预期值放在RAX中。

现在考虑以下代码:

char *c = "hello";
NSData *data = [NSData dataWithBytes:c length:strlen(c)];
NSString *s = [[NSString alloc] initWithData:data
                                    encoding:NSASCIIStringEncoding];
printf("s has address %p\n", s);

以及以下探测:

objc$target:NSPlaceholderString:-initWithData?encoding?:return
{
    printf("Returning from -[NSPlaceholderString initWithData:encoding:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

使用DTrace运行时,我得到以下输出:

s has address 0x7fcd92414ea0
Returning from -[NSPlaceholderString initWithData:encoding:]
    return value = 0x600

如您所见,地址(即返回值)不匹配。实际上,0x600是kCFStringEncodingASCII的值,它是NSASCIIStringEncoding的核心基础对应物。在某些时候,方法调用的方法或函数将0x600移动到RAX,这是DTrace 错误地认为是返回值的值。