2012-04-20 23 views
9

Otrzymałem zgłoszenie awarii za pośrednictwem AirBrake.io, które nie jest symbolizowane. Ponieważ raport o awariach nie ma dokładnie takiego samego formatu, jak w przypadku crashlogu Apple, nie mogę go tak zwyczajnie upuścić na XCode, więc wziąłem ten sam kompilator z mojego archiwum XCode, próbując go symbolizować w linii poleceń. Z następującym wynikiem:Atos i dwarfdump nie będą symbolizować mojego adresu

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

Jestem absolutnie pewien, że używam tej samej wersji co raport o awarii. Próbowałem też z karłem 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. 

Brak wyników. Czy jest coś jeszcze poza użyciem niewłaściwego pliku dSYM, który mógłbym zrobić źle? Wiem, że to jest poprawne, ponieważ jest to wersja, o której mowa w raporcie o awariach w AirBrake i jest w moim archiwum XCode.

Wszelkie pomysły/wskazówki są mile widziane!

Odpowiedz

9

Przede wszystkim należy sprawdzić, czy dSYM jest naprawdę poprawna dla tej aplikacji:

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

Zarówno powinien zwrócić ten sam rezultat.

Następny Sprawdź, czy dSYM ma jakiejkolwiek uzasadnionej zawartości

dwarfdump --all kidsapp.app.dSYM 

To powinno dać przynajmniej niektóre informacje, inne niż not found.

Domyślam się, że dSYM jest uszkodzony. Zasadniczo możesz użyć narzędzia do zgłaszania awarii, które zawiera pełny raport o awariach z wszystkimi wątkami i informacjami o śledzeniu ostatniego wyjątku. Polecam używanie czegoś na podstawie PLCrashReporter, np. QuincyKit (Open Source SDK + Server + symbolikacja na twoim mac) lub HockeyApp (Open Source SDK + płatna usługa + symbolizacja po stronie serwera) (Uwaga: jestem jednym z programistów!)

+0

Mam ten sam problem. Mam zgłoszoną awarię, która zapewnia śledzenie stosu, ale żaden z symboli z mojego projektu, który nie znajduje się w stosie, nie znajduje się w dSYM mojego archiwum. Identyfikatory UU są zgodne, ale symbole są wyłączone. Jak to możliwe i jak mogę to rozwiązać? Czy jabłko modyfikuje plik binarny w jakiś sposób przed wydaniem go do sklepu z aplikacjami, co zaburza wyrównanie z moim dSYM? – NSProgrammer

+0

Musisz uwzględnić slajd binarny i adres początkowy aplikacji. Nie można po prostu użyć adresu pamięci ze śledzenia stosu. Wystarczy użyć skryptu symbolicatecrash z Xcode, który wykonuje wszystko, czego potrzebujesz. – Kerni

+0

Ale jeśli wszystko, co mam, to symbole (powinienem był powiedzieć zrzut stosu, a nie ślad), który czysto daje mi wartości szesnastkowe, w jaki sposób wziąć pod uwagę "slajd"? – NSProgrammer

22

Użyłem następującej arytmetyki it out:

slide + stack address - load address = symbol address

i

stack address jest wartość hex otrzymuję od mojego stos zrzutu raportu katastrofy (a nie polecenie .crash plik, tylko zrzut stosu).

i

slide jest vmaddr z cmd LC_SEGMENT gdy uruchomiony otool -arch armv7 -l APP_BINARY_PATH. Mój zwykle kończy się jako 0x00001000.

i

load address jest skomplikowany utwór. W rzeczywistości jest to różnica między najniższym adresem stosu głównego wątku i PIERWSZYM adresem części mojego pliku binarnego, która zawiera symbole podczas uruchamiania dwarfdump --arch armv7 --all DSYM_BINARY_PATH. Jest to po prostu symboliczny adres funkcji main. Więc jeśli twój najniższy adres awarii to 0x8000, a twój symboliczny adres głównej funkcji to 0x2000, twój load address to 0x6000.

Teraz za pomocą WSZYSTKICH tych elementów mogę obliczyć adres symbolu i umieścić go w atos lub dwarfdump: dwarfdump --lookup SYM_ADDR --arch armv7 APP_BINARY_PATH.

Przykład zrzutu (widać, że load address był 0x00003af4):

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

Plik: /Users/user/Desktop/MyApp.xcarchive/dSYMs/MyApp.app.dSYM/Zawartość/zasoby/KARŁOWATA/MojaApl (ARMv7)

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

0x00000024 [0x00003af4 - 0x00003b4e) główne

0x00000098: [0x00003b50 - 0x00003d8c) - [MyAppDelegate aplikacji: didFinishLaunchingWithOptions:]

... reszta wysypisko

Najtrudniej było wiedząc, że jedna z 2 statycznych bibliotek I” d zawierał ich symbole rozebrane przed umieszczeniem linka do pliku binarnego mojej aplikacji! To pozostawiło OGROMNĄ szczelinę adresów symboli, więc skończyłem z dwiema trzecimi symboli, których potrzebowałem w moim dSYM.

Należy upewnić się, że następujące flagi ustawiono na NIE w projekcie xcode dla statycznych bibliotek, tak aby po połączeniu z nim można było wciągnąć symbole do pliku binarnego aplikacji (które można następnie usunąć): COPY_PHASE_STRIP, DEAD_CODE_STRIPPING, i STRIP_INSTALLED_PRODUCT.

Teraz możesz zapytać: "co mam zrobić, jeśli zrzut stosu nie zawiera głównej funkcji, ponieważ nie znajduje się w głównym wątku, więc nie mogę uzyskać adresu stosu głównej funkcji?". Na to odpowiedziałbym: "Nie mam pojęcia"! Po prostu skrzyżuj palce i miej nadzieję, że możesz uzyskać ślad stosu zawierający adres symbolu lub skorzystać z systemu zgłaszania awarii, który naśladuje dzienniki awarii Apple, takie jak PLCrashReporter.

[EDIT 26 maja 2013] -

Została wniesiona do mojej uwagi, że load address jest naprawdę adres binarny Mach-O. Chociaż to, co opisałem powyżej, może często zadziałać - nie jest właściwie poprawne. Można to uzyskać za pomocą RAPORTU CRASH, jednak celem tej odpowiedzi było dostarczenie symboli awarii, gdy nie masz raportu o awarii. Najlepszym sposobem, aby dowiedzieć się, kiedy load address chciałbym oznaczyć symbol, jest upewnienie się, że loguję load address z stack addresses.

Osobiście stworzyłem system do rejestrowania awarii (bez raportów o awariach) i wysyłania ich do wiadra S3, w którym mogę je później pobrać w celu debugowania. Kiedy rozpoczynam swoją aplikację, buforuję slide, load address i main function address do wykorzystania, jeśli moja aplikacja ulega awarii i wysyłam stack addresses.

UWAGA: funkcje dyld używać #include <mach-o/dyld.h>

slide = adres zwrócony przez _dyld_get_image_vmaddr_slide(0)

load address = adres zwrócony przez _dyld_get_image_header(0)

main function address = ostatni adres w [NSThread callStackReturnAddresses] gdy nazwie na głównym wątek

W czasie zderzenia jestem sur e zalogować [NSThread callStackReturnAddresses] i [NSThread callStackSymbols] a także architektury, który można pobrać poprzez tę metodę:

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

    return arch; 
} 

ja nie wiem jeszcze jak odróżnić ARMv7 i armv7s chociaż.

Może to pomóc w przyszłości. Mam zamiar zabrać wszystko, czego się nauczyłem i zamienić to w proste narzędzie do zderzenia - lepsze niż narzędzie natos (prawdopodobnie natos v2).

zaktualizowałem Natos celu wspierania dostarczania load address Ręczne: https://github.com/NSProgrammer/natos

+3

Stworzyłem narzędzie wiersza poleceń, aby wykonać całą ciężką pracę. Wystarczy 1) ścieżka xcarchive, 2) symbol adresu stosu głównej funkcji, 3) adres stosu żądanego symbolu, 4) interesującą architekturę. Znajduje się na github: https://github.com/nob1984/natos – NSProgrammer

+0

Fajnie napisany, ale niestety jest poważny błąd: adres obciążenia jest ** NIE ** co napisałeś. Adres obciążenia można znaleźć w sekcji obrazów binarnych raportu o awarii i jest to adres początkowy zakresu adresów odpowiedniego pliku binarnego. – Kerni

+0

Użyłem twoich narzędzi, ale jak mogę uzyskać _mainFunctionStackAddress? Znajduję adres przez dwarfdump mój plik dsym i użyłem go, ale wynik jaki mi dał był taki sam jak wyjaśniłem atos, wciąż nie mogę znaleźć właściwej pozycji punktu załamania. – Zhou

0

myślę, że to stanowisko może pomóc, https://stackoverflow.com/a/12559150/1773317. Joe's commit rozwiązał mój problem.

Powodem jest to, że moje pliki .app i .dSYM nie mogą być indeksowane za pomocą spotlight, więc mój XCode nie może prawidłowo oznaczyć informacji o awarii.

2

Dla kogo że pewne czasy nie mają wartości dla obciążenia jak to Adres:

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 

Stworzyłem prostą bash mi pomóc debug:

#! /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 

To właśnie czyta ścieżkę do aplikacji, nazwę aplikacji, adres środowiska wykonawczego i wartość po znaku "+" (wartość dziesiętna), a następnie znajdź wartość adresu ładowania, aby uruchomić polecenie atos.