是否可以在 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 未被引用”