2012-04-20 4 views
9

Я получил сообщение о сбое через AirBrake.io, который не является символом. Поскольку отчет о сбое не соответствует точному краху Apple, я не могу просто удалить его на XCode, как обычно, поэтому я взял ту же самую сборку из архива XCode, которая пыталась ее символизировать в командной строке. Со следующим сообщением:atos и dwarfdump не будут обозначать мой адрес

$ atos -o kidsapp.app/kidsapp 0x0002fc4c 
0x0002fc4c (in kidsapp) 

Я абсолютно уверен, что использую ту же сборку, что и отчет об аварии. Поэтому я также пробовал с карликом:

$ dwarfdump --lookup 0x0002fc4c --arch armv7 kidsapp.app.dSYM 
---------------------------------------------------------------------- 
File: kidsapp.app.dSYM/Contents/Resources/DWARF/kidsapp (armv7) 
---------------------------------------------------------------------- 
Looking up address: 0x000000000002fc4c in .debug_info... not found. 
Looking up address: 0x000000000002fc4c in .debug_frame... not found. 

Также нет результата. Есть ли что-нибудь еще, кроме использования неправильного файла dSYM, который я мог бы сделать неправильно? Я знаю, что это правильно, так как это версия, упомянутая в отчете о сбое в AirBrake, и это в моем архиве XCode.

Любые идеи/советы приветствуются!

ответ

9

Прежде всего, проверьте, если dSYM действительно правильный для этого приложения:

dwarfdump --uuid kidsapp.app/kidsapp 
dwarfdump --uuid kidsapp.app.dSYM 

Оба должны возвращать тот же результат.

Следующая проверка если dSYM имеет любое легитимное содержимое

dwarfdump --all kidsapp.app.dSYM 

Это должно дать хоть какую-то информацию, кроме not found.

Я думаю, что dSYM поврежден. В общем, вы можете использовать репортаж об аварии, который дает вам полный отчет о сбое со всеми потоками и информацией о последнем обратном исключении. Я рекомендую использовать что-то на основе PLCrashReporter, например. QuincyKit (Open Source SDK + Server + symbolication на вашем Mac) или HockeyApp (Open Source SDK + платная услуга + символическая сторона сервера) (Примечание: я являюсь одним из разработчиков обоих!)

+0

У меня тот же вопрос. У меня есть сообщение об аварии, которое предоставляет трассировку стека, но ни один из символов моего проекта, который попадает в стек, не найден в dSYM моего архива. UUIDs совпадают, но символы все выключены. Как это возможно и как я могу это решить? Является ли яблоко каким-то образом модифицировать двоичный файл перед тем, как отпустить его в хранилище приложений, таким образом развращая выравнивание с моим dSYM? – NSProgrammer

+0

Вам нужно будет учитывать слайды двоичного и стартового адресов приложения. Вы не можете просто использовать адрес памяти из трассировки стека. Просто используйте скрипт symbolicatecrash из Xcode, который делает все, что вам нужно. – Kerni

+0

Но если все, что у меня есть, являются символами (я должен был сказать, что дамп стека, а не трассировка), который чисто дает мне шестнадцатеричные значения, как мне взять «слайд»? – NSProgrammer

22

Я использовал следующую арифметику для иллюстрации это:

slide + stack address - load address = symbol address

и

stack address является шестнадцатеричное значение я получаю от моего отчета об ошибке стека дампа (не .crash файл, просто стек дампа).

и

slide является vmaddr из LC_SEGMENT ЦМД при запуске otool -arch armv7 -l APP_BINARY_PATH. Шахта обычно заканчивается 0x00001000.

и

load address является сложным кусок. На самом деле это разница между самым нижним адресом стека основного потока и адресом FIRST части моего двоичного файла, которая содержит символы при запуске dwarfdump --arch armv7 --all DSYM_BINARY_PATH. Это просто символический адрес функции main. Поэтому, если ваш самый нижний адрес сбоя - 0x8000, а символический адрес вашей основной функции - 0x2000, то ваш load address равен 0x6000.

Теперь со всеми этими частями я могу вычислить адрес символа и поместить его в atos или dwarfdump: dwarfdump --lookup SYM_ADDR --arch armv7 APP_BINARY_PATH.

Пример дампа (вы можете увидеть, что load address был 0x00003af4):

----------------------------------------------------------------------

Файл: /Users/user/Desktop/MyApp.xcarchive/dSYMs/MyApp.app.dSYM/Содержание/Ресурсы/DWARF/MyApp (ARMv7)

----------------------------------------------------------------------

0x00000024: [0x00003af4 - 0x00003b4e) Главный

0x00000098: [0x00003b50 - 0x00003d8c) - [MyAppDelegate применения: didFinishLaunchingWithOptions:]

... остальная часть свалки

Самая трудная часть была понимая, что один из 2-х статических библиотек I» d включили, если бы их символы разделились, прежде чем ссылаться на двоичный файл моего приложения! Это оставило ОГРОМНЫЙ пробел в символьных адресах, поэтому я только закончил с двумя третями символов, которые мне нужны в моем dSYM.

Обязательно иметь следующие флаги, установленные для NO в вашем статическом проекте библиотеки Xcode, так что, когда вы ссылаетесь на него, вы можете тянуть в символах, чтобы ваше приложение бинарного (которые впоследствии могут быть удалены): COPY_PHASE_STRIP, DEAD_CODE_STRIPPING, и STRIP_INSTALLED_PRODUCT.

Теперь вы можете спросить: «Что мне делать, если дамп стека не включает основную функцию, так как он не находится в основном потоке, так что я не могу получить адрес стека главной функции?». На это я бы ответил: «У меня нет подсказки!». Просто скрестите пальцы и надейтесь, что вы можете получить трассировку стека, которая включает в себя адрес символа, или использовать систему отчетов о сбоях, которая имитирует журналы сбоев Apple, такие как PLCrashReporter.

[EDIT 26 мая 2013] -

Это было доведено до моего сведения, что load address действительно адрес маш-о двоичной системе. Хотя то, что я описал выше, часто может работать - на самом деле это неверно. Это можно получить с помощью CRASH REPORT, однако точкой этого ответа было предоставление символов сбоя, когда у вас нет отчета о сбоях. Лучший способ, которым я пришел к выяснению load address, когда вы хотите его символизировать, - это убедиться, что я зарегистрировал load address с stack addresses.

Я лично создал систему для регистрации сбоев (не отчетов о сбоях) и отправки их в ведро S3, где я могу получить их позже для отладки. Когда я запускаю свое приложение, я кэширую slide, load address и main function address для использования, если мое приложение падает, и я посылаю stack addresses.

Примечание: функции dyld использовать #include <mach-o/dyld.h>

slide = адрес, возвращаемый _dyld_get_image_vmaddr_slide(0)

load address = адрес, возвращаемый _dyld_get_image_header(0)

main function address = последний адрес [NSThread callStackReturnAddresses] когда призвал главный нить

В аварийное время я схожу е войти [NSThread callStackReturnAddresses] и [NSThread callStackSymbols], а также архитектуру, которую можно восстановить, имея этот метод:

- (NSString*) arch 
{ 
    NSString* arch = 
#ifdef _ARM_ARCH_7 
     @"armv7"; 
#elif defined (_ARM_ARCH_6) 
     @"armv6"; 
#else 
     nil; 
#endif 

    return arch; 
} 

Я пока не знаю, как провести различие между ARMv7 и armv7s хотя.

Так что это может помочь в будущем. Я планирую взять все, что я узнал, и превратить это в простой инструмент крушения - лучше, чем инструмент natos (возможно, natos v2).

Я обновил natos для поддержки снабжающих load address вручную: https://github.com/NSProgrammer/natos

+3

Я создал инструмент командной строки, чтобы выполнить всю тяжелую работу. Просто нужно 1) путь xcarchive, 2) символ адреса стека основной функции, 3) адрес стека нужного символа, 4) интересующая архитектура. Он расположен на github: https://github.com/nob1984/natos – NSProgrammer

+0

Хорошая запись, но, к сожалению, в нем есть большая ошибка: адрес загрузки ** НЕ **, что вы написали. Адрес загрузки можно найти в разделе двоичных изображений в отчете о сбое и является начальным адресом диапазона адресов соответствующего двоичного файла. – Kerni

+0

Я использовал ваши инструменты, но как я могу получить _mainFunctionStackAddress? Я нахожу адрес dwarfdump моего dsym-файла и использовал его, но результат, который он мне дал, был таким же, как объяснил атос, я все еще не могу найти правильную позицию точки срыва. – Zhou

0

Я думаю, что этот пост может помочь вам, https://stackoverflow.com/a/12559150/1773317. Джо совершил мою проблему.

Причина в том, что мои файлы .app и .dSYM не могут быть проиндексированы прожектором, поэтому мой XCode не может правильно идентифицировать информацию о сбое.

2

Для кого что определенное время не имеет значения для нагрузки Адрес, как это:

Jan 14 11:02:39 Dennins-iPhone AppName[584] <Critical>: Stack Trace: (
    0 CoreFoundation      0x2c3084b7 <redacted> + 150 
    1 libobjc.A.dylib      0x39abec8b objc_exception_throw + 38 
    2 CoreFoundation      0x2c21cc35 CFRunLoopRemoveTimer + 0 
    3 AppName        0x0005a7db AppName + 272347 

Я создал простой Баш, чтобы помочь мне отлаживать:

#! /bin/bash 
read -p "[Path] [App Name] [Stack Address] [Relative Address] " path appName runtimeAddress relativeAddress 
loadAddress=`echo "obase=16;ibase=10;$((runtimeAddress-relativeAddress))" | bc` 
atos -o $path/Payload/$appName.app/$appName -l $loadAddress $runtimeAddress -arch armv7 

Он просто читает путь к приложению, имя приложения, адрес времени выполнения и значение после сигнала «+» (десятичное значение), а затем найдите значение для адреса загрузки для запуска команды atos.