Как получить строку аварии и метод, как Crashlytics, а также с открытым исходным кодом PLCrashReporter

Как я уже говорил, я пытаюсь восстановить строку сбоя, а также функцию, в которой она встречается.

Мне нужно измерить, что я пробовал следующий код в AppDelegate, и я получаю, что стек не символизирован, а класс, а также ошибка выбрана:

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

void uncaughtExceptionHandler(NSException *exception) {

    NSLog(@"Exception description - %@",[exception description]);
    NSLog(@"Exception name - %@", [exception name]);
    NSLog(@"Reason - %@", [exception reason]);
    NSLog(@"\n\n - %@", [exception callStackSymbols]);
    NSLog(@"\n\n - %@", [exception callStackReturnAddresses]);
}

Но, используя их, я не получаю строку сбоя, поскольку я намерен сохранить ее в CoreData.

Также меня не интересует xcode aproaches как: "Добавить точку исключения исключений" или другие aproaces как: XCode > Окно > Устройствa > просмотр журналов сбоев на устройстве, тест Flight aproaches или реализация других фреймворков в приложении как Crashlytics.

Я упоминаю об этом, потому что мне очень интересно, как это можно сделать с помощью кода.

Также я могу получить dsym из архива приложения, когда он сделан, и загрузите его на сервер с помощью RunScript, написанного с помощью Bash. Поэтому я могу использовать dsym, если это необходимо для достижения линии сбоя.

Также я знаю, что следующий aproach можно использовать для получения текущей строки кода: LINE и _FUNCTION__, чтобы получить имя функции.

Также, если вы можете предоставить примеры кода из open-source PLCrashReporter, как они это сделают, я буду очень благодарен.

Чем вы все заранее!:)

Ответ 1

В основном существуют два типа сбоев:

  • Невозможно удалить исключения, которые можно найти с кодом, похожим на ваш
  • Аварии на основе сигналов, которые могут быть захвачены обработчиками сигналов (или обработчиками Mach Exception, но которые не будут захватывать все сигналы)

Затем, поймав любую из этих сбоев, вам нужно получить трассировку стека (из всех потоков). [NSException callStackSymbols] предоставит вам некоторые символы (только для сбоя исключений), для большого количества символов ОС он будет показывать только redacted, для вашего приложения он предоставит некоторые символы, если вы не разделите их с вашего двоичного файла. Рекомендуется удалить символы из двоичного файла, чтобы уменьшить размер файла (много), и эти символы также никогда не будут содержать имена файлов и номера строк.

Поэтому вместо этого вам нужно получить следующую информацию из фреймов стека: двоичный, двоичный UUID, архитектура процессора и адрес памяти. [NSException callStackReturnAddresses] предоставит вам адреса памяти, но снова только для сбоя на основе исключения. Кроме того, он не обеспечивает двоичное изображение, соответствующее адресу памяти.

Таким образом, вам нужно получить список двоичных изображений с диапазоном адресов в памяти, каждый из которых содержит два бинарных изображения, а также способ получить адреса памяти фреймов стека для потоков также для сбоев, основанных на исключениях. Если вы хотите узнать, как это происходит, вы в основном можете взглянуть на ВСЕ код PLCrashReporters, поскольку это цель проекта с открытым исходным кодом, и это не та область StackOverflow, которая объясняет такие сложные сценарии. Прочтите код, документацию и узнайте:) Чтобы дать вам краткое описание: не делайте этого самостоятельно, просто используйте PLCrashReporter.

Теперь, чтобы получить символы, включая имена файлов и номера строк, вам необходимо символизировать отчеты о сбоях, используя символы ОС для соответствующей версии ОС и соответствующей архитектуры ЦП с устройства, на котором произошел сбой. Также вам нужны пакеты символов (dSYM) из точных двоичных (и фреймворков), которые вызвали отчет о сбое из вашего приложения. Каждое двоичное изображение имеет уникальный UUID и файл символов, который вы используете для получения символов, должен иметь один и тот же UUID для той же архитектуры процессора.

Теперь вам нужно запустить инструмент atos, чтобы получить символы для определенного адреса памяти из определенного файла символов. Следующий ответ показывает, как это сделать: fooobar.com/questions/16908/...

В качестве альтернативы вы можете использовать symbolicatecrash.pl script, который поставляется с Xcode и принимает стандартный отформатированный отчет о сбоях Apple (у PLCrashReporter есть инструмент преобразования для создания таких отчетов из более компактных отчетов).

Ответ 2

Вы можете использовать __PRETTY_FUNCTION__ в своих журналах, что даст вам строку, класс и имя функции.

NSLog(@"%@", __PRETTY_FUNCTION__);

Вы можете заполнить остальную часть журнала любой другой информацией, которая вам нравится.