Определить совместимые с DTrace структуры для объектов Objective-C.

Я пытаюсь написать сценарий DTrace, который покажет мне параметр, переданный в -[NSURLConnection sendSynchronousRequest:returningResponse:error:], и я не могу найти структуру, которая работает для извлечения строки из переданного параметра NSString. На этот вопрос есть ответ, который работает для приложений OS X, но не работает для моего приложения, которое использует симулятор iOS.

Хотя я ищу решение для этого конкретного примера, мне гораздо больше интересно узнать, как лучше всего определить/обнаружить базовую структуру памяти для любого заданного объекта Objective-C. Как видно из тестового приложения для OS X, которое я написал, параметр NSString не всегда содержит необработанные строковые данные в одном и том же месте. В случае, когда это __NSCFString, кажется, находится (с префиксом длины) в 16 байтах. В случае, когда это строка __NSCFConstant, это где-то еще, что не сразу очевидно, глядя на необработанный дамп памяти.

Если в системных заголовках определены структуры, которые покажут мне, что я ищу, это было бы хорошим первым шагом, но я думаю, что LLDB также должен иметь возможность показывать мне полезные подсказки.

Сравнение дампа памяти NSString


person Mark Edington    schedule 27.10.2013    source источник


Ответы (2)


Теоретически Class-dump должен иметь возможность проверять файл Mach-O и сообщать об объявлениях. для ваших классов Objective C.

Когда я в последний раз пытался использовать Class-dump, у меня ничего не вышло; Я не могу точно вспомнить почему, но теперь я вижу, что есть возможная альтернатива, а именно Hopper. В любом случае, прочитав статью Злоупотребление средой выполнения Objective C, я использовал gdb для проверки адресного пространства; в отличие от вас, я использовал DTrace, чтобы остановить процесс при входе в метод, а затем проверил память, адресованную arg2. Если в вашем случае вы не видите разумной строки, я предлагаю вам искать указатели и следовать им.

Обратите внимание, что в вашем вопросе использовалась фраза «DTrace-совместимый». Это поднимает интересный момент: dtrace(1) — это компилятор, и он не обязан упаковывать структуры так же, как все, что использовалось для сборки вашей жертвы. В Solaris dtrace(1) соответствует ABI данной платформы, будь то SPARC или x86. Я не исследовал его поведение в MacOS, но оно может отличаться, так что имейте это в виду, особенно если dtrace дает неожиданные результаты.

person Robert Harris    schedule 29.10.2013

Компилятор может сделать практически все с кодом ObjC, если он соответствует общедоступному определению объективной среды выполнения c.

Я думаю, что вы выбрали неправильный объект для начала своего исследования: NSString (наряду с NSNumber) имеет несколько версий, которые выбираются в зависимости от вашего использования. Например. ваша константа времени компиляции NSString, вероятно, представлена ​​​​как:

struct __builtin_NSString {
    const int *isa; // point to __NSConstantStringClassReference
    const char *str; // point to some byte array under __cfstring segment
    unsigned int length; // size of that byte array
};

Вы также можете найти свою константу NSString (или CFString), проверив сегмент __cfstring, например через инструмент otool -s __DATA __cfstring.

Я не знаю ни одного метода, который позволил бы вам декомпилировать любой объект ObjC в форму C-структуры. Мое предложение состоит в том, чтобы посмотреть, как осуществляется доступ к различным полям объектов, путем дизассемблирования вашей программы. Например. вы можете добавить точку останова к сеттерам и геттерам ваших свойств.

Если вам удобно, вы также можете изучить исходный код компилятора, ответственного за преобразование кода высокого уровня в промежуточное (в случае компилятора на основе LLVM) представление: CGObjCMac, CGObjC, CGObjCRuntime.

person Kentzo    schedule 29.10.2013