7

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

4

1 回答 1

5

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

Bill Bumgarner 有一篇关于将消息追踪到 nil的帖子,其中他说:

Aside:objc_msgSend()的返回目前无法通过 dtrace 进行跟踪。鉴于该函数实际上并没有返回,这并不奇怪——就 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()or 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 是 .Core kCFStringEncodingASCIIFoundation 对应的值NSASCIIStringEncoding。在某些时候,方法或方法调用的函数将 0x600 移动到 RAX,这就是 DTrace错误地认为是返回值的值。

于 2011-09-03T00:54:37.933 回答