atos и dwarfdump не будут символизировать мой адрес
Я получил отчет о сбое через AirBrake.io, который не является символом. Так как отчет о сбое не имеет такого же формата, как и журнал сбоя Apple, я не могу просто поместить его в XCode как обычно, поэтому я взял точно такую же сборку из своего архива XCode, пытаясь обозначить его в командной строке. Со следующим результатом:
$ atos -o kidsapp.app/kidsapp 0x0002fc4c
0x0002fc4c (in kidsapp)
Я абсолютно уверен, что использую ту же сборку, что и отчет о сбое. Поэтому я также попытался с dwarfdump:
$ 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.
Любые идеи / советы приветствуются!
6 ответов
Прежде всего, проверьте, действительно ли 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 + символика на вашем Mac) или HockeyApp (Open Source SDK + Платный сервис + серверная символика) (Примечание: я один из разработчиков обоих!)
Я использовал следующую арифметику, чтобы понять это:
slide
+ stack address
- load address
знак равно symbol address
а также
stack address
это шестнадцатеричное значение, которое я получаю из своего отчета о сбое дампа стека (не файл.crash, просто дамп стека).
а также
slide
это vmaddr команды LC_SEGMENT при запуске otool -arch armv7 -l APP_BINARY_PATH
, Мой обычно заканчивается 0x00001000.
а также
load address
это сложный кусок. Это на самом деле разница между адресом самого нижнего стека основного потока и ПЕРВЫМ адресом части моего двоичного файла, который содержит символы при запуске 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/Contents/Resources/DWARF/MyApp (armv7)
----------------------------------------------------------------------
0x00000024: [0x00003af4 - 0x00003b4e) main
0x00000098: [0x00003b50 - 0x00003d8c) - [приложение MyAppDelegate: didFinishLaunchingWithOptions:]
... остальная часть свалки
Самым сложным было понять, что в одной из 2-х статических библиотек, которые я включил, их символы были удалены, прежде чем они стали ссылками на двоичный файл моего приложения! Это оставило ОГРОМНУЮ пропасть в адресах символов, поэтому я получил только две трети символов, которые мне нужны в моем dSYM.
Убедитесь, что в вашем проекте xcode статических библиотек установлены следующие флаги NO, чтобы при ссылках на них можно было вставлять символы в двоичный файл вашего приложения (который впоследствии можно будет удалить): COPY_PHASE_STRIP
, DEAD_CODE_STRIPPING
, а также STRIP_INSTALLED_PRODUCT
,
Теперь вы можете спросить: "Что мне делать, если дамп стека не включает основную функцию, поскольку он не находится в основном потоке, поэтому я не могу получить адрес стека основной функции?". На это я бы ответил: "Понятия не имею!". Просто скрестите пальцы и надейтесь, что вы можете получить трассировку стека, включающую адрес символа, или использовать систему отчетов о сбоях, которая имитирует журналы сбоев Apple, такие как PLCrashReporter.
[РЕДАКТИРОВАТЬ 26 мая 2013 г.] -
Было доведено до моего сведения, что load address
действительно адрес двоичного файла mach-o. Хотя то, что я описал выше, часто может работать - это не совсем правильно. Это может быть получено с помощью 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).
Я обновил натос, чтобы поддержать поставку load address
вручную: https://github.com/NSProgrammer/natos
Для кого это определенное время не имеет значения для адреса загрузки, как это:
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
Я создал простой bash, чтобы помочь мне отладить:
#! /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.
Итак, мой случай: я получаю строки сбоя из NSException.callStackSymbols.
Трассировка аварийного стека выглядит следующим образом:
2 AppName 0x00000001006c75b4 AppName + 2356660\r3 AppName 0x00000001004f5cfc AppName + 449788\r4 UIKit 0x000000018c0a8968 \u003credacted\u003e + 108\r5 UIKit 0x000000018c0a9328 \u003credacted\u003e + 28\r6 UIKit 0x000000018beea250 \u003credacted\u003e + 1320\r7 UIKit 0x000000018beede98 \u003credacted\u003e + 188\r8 UIKit 0x000000018bcb5820 \u003credacted\u003e + 116\r9 UIKit 0x000000018bbdec88 \u003credacted\u003e + 760\r10 UIKit 0x000000018bbde610 \u003credacted\u003e + 312\r11 UIKit 0x000000018bbde31c \u003credacted\u003e + 296\r12 UIKit 0x000000018bbde3bc \u003credacted\u003e + 456\r13 QuartzCore 0x0000000185b93b7c \u003credacted\u003e + 284\r14 libdispatch.dylib 0x00000001811a8a2c \u003credacted\u003e + 16\r15 libdispatch.dylib 0x00000001811b5654 \u003credacted\u003e + 1012\r16 CoreFoundation 0x0000000181851650 \u003credacted\u003e + 12\r17 CoreFoundation 0x000000018184f1a8 \u003credacted\u003e + 2272\r18 CoreFoundation 0x000000018176f488 CFRunLoopRunSpecific + 552\r19 GraphicsServices 0x0000000183735020 GSEventRunModal + 100\r20 UIKit 0x000000018bc09cc0 UIApplicationMain + 236\r21 AppName 0x000000010048f714 AppName + 30484\r22 libdyld.dylib 0x000000018120dfc0 \u003credacted\u003e + 4
Не включайте битовый код, так как Apple может перекомпилировать ваш код, и файлы dsym из вашего архива в Организаторе не будут совпадать.
Запустите такой скрипт:
#!/bin/bash
appName=AppName
runtimeAddress=0x00000001006c75b4
relativeAddress=2356660
loadAddress=`echo "obase=16;ibase=10;$((runtimeAddress-relativeAddress))" | bc`
atos -o $appName.app/$appName -l $loadAddress $runtimeAddress -arch arm64
Предполагая, что вы создали test.sh (коснитесь test.sh). Если невозможно запустить sctipt (./test.sh) из-за проблем с разрешениями: вызовите chmod +x test.sh Теперь./test.sh должен работать. И сформировать результат.
Также возможно обозначить файл сбоя с помощью файла AppName.app.dSYM:
#!/bin/bash
appName=AppName
runtimeAddress=0x00000001006c75b4
relativeAddress=2356660
loadAddress=`echo "obase=16;ibase=10;$((runtimeAddress-relativeAddress))" | bc`
atos -o $appName.app.dSYM/Contents/Resources/DWARF/$appName -l $loadAddress $runtimeAddress -arch arm64
Вы можете попробовать и использовать скрипт, который я написал для символики, используя команду atos:
Я думаю, что этот пост может помочь вам, /questions/47685671/sboj-simvolnogo-sboya-na-xcode-45/47685685#47685685. Коммит Джо подошел к моей проблеме.
Причина в том, что мои файлы.app и.dSYM не могут быть проиндексированы в центре внимания, поэтому мой код XCode не может правильно символизировать информацию о сбое.