是否可以在 dtrace 中获取 objc 方法的结果?

Posted

技术标签:

【中文标题】是否可以在 dtrace 中获取 objc 方法的结果?【英文标题】:Is it possible to get the result of objc method in dtrace? 【发布时间】:2011-08-12 22:44:36 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

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

除此之外: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: 的返回值。不过这只是运气,可能是由-initWithInt: 调用的函数(例如CFNumberCreate()CFMakeCollectable())引起的,最终将预期值放入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 错误地 认为是返回值的值。

【讨论】:

以上是关于是否可以在 dtrace 中获取 objc 方法的结果?的主要内容,如果未能解决你的问题,请参考以下文章

DTrace objc:无效的探针说明符:“$1 未被引用”

在dtrace中获取Erlang消息的消息内容

Leopard 上的 DTrace:没有指定探针,即使我指定了探针

dtrace:如何从文件中获取符号链接目标

从 C 程序访问 dtrace 探针

是否可以在 Mac OS X 上通知 DTrace 动态生成的代码?