В итоге: нет, вы не можете получить возвращаемое значение метода Objective-C в тесте DTrace.
У Билла Бумгарнера есть запись о сообщениях трассировки до nil вчто он говорит следующее:
В сторону: objc_msgSend()
возвращение не может быть отслежено через dtrace в это время.Не удивительно, учитывая, что функция на самом деле не возвращает - что касается dtrace, то это всего лишь преамбула.
Сообщение в блоге довольно старое (январь 2008 г.) и использует провайдера 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
, которое является эквивалентом Core Foundation NSASCIIStringEncoding
.В какой-то момент метод или функция, вызываемая этим методом, переместили 0x600 в RAX, и это значение, которое DTrace ошибочно считало возвращаемым значением.