Можно ли получить результат метода objc в dtrace?
Я написал действие, которое запускается при возврате любого метода objc (objc:::return). Сейчас мне нужно получить возвращаемое значение. Является ли это возможным?
1 ответ
В итоге: нет, вы не можете получить возвращаемое значение метода Objective C в тесте DTrace.
У Билла Бумгарнера есть сообщение о трассировке сообщений до нуля, в котором он говорит следующее:
В сторону:
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
который является основным партнером Фонда NSASCIIStringEncoding
, В какой-то момент метод или функция, вызываемая этим методом, переместили 0x600 в RAX, и это значение, которое DTrace ошибочно считало возвращаемым значением.