2015-12-08 3 views
5

Ziel:Wie "manuell" symbolicate [NSThread callStackSymbols] (erhalten die Startadresse für atos) (iOS)

Ich möchte den "Output" von [NSThread callStackSymbols] symbolicate. Hinweise

Seite:

Ich weiß, wie das mit Crash-Protokollen zu tun. Ich muss jedoch einige Probleme untersuchen, bei denen ich den Call-Stack betrachten möchte. Leider sind heutzutage die Adressen des Frameworks <redacted>. Einen Absturz an den richtigen Stellen zu verursachen (oder am Ende - siehe Ende meiner Frage) ist nicht wirklich akzeptabel, aber wenn ich keine andere Lösung finden kann, wird es der richtige Weg sein.

Ich muss meine Tests auf einem Gerät ausführen, damit ich den Simulator nicht verwenden kann.

Aktuelle Ansatz:

Als ich das nennen:

NSLog(@"call stack:\n%@", [NSThread callStackSymbols]); 

ich diese Ausgabe:

2015-12-08 15:04:03.888 Conversion[76776:4410388] call stack: 
(
    0 Conversion       0x000694b5 -[ViewController viewDidLoad] + 128 
    1 UIKit        0x27259f55 <redacted> + 1028 
    ... 
    9 UIKit        0x274f67a7 <redacted> + 134 
    10 FrontBoardServices     0x2b358ca5 <redacted> + 232 
    11 FrontBoardServices     0x2b358f91 <redacted> + 44 
    12 CoreFoundation      0x230e87c7 <redacted> + 14 
    ... 
    16 CoreFoundation      0x23038ecd CFRunLoopRunInMode + 108 
    17 UIKit        0x272c7607 <redacted> + 526 
    18 UIKit        0x272c22dd UIApplicationMain + 144 
    19 Conversion       0x000767b5 main + 108 
    20 libdyld.dylib      0x34f34873 <redacted> + 2 
) 

("Conversion" in dieser Ausgabe ist die App.)

Jetzt kann ich diesen Befehl verwenden, um die Anzeige "zu symbolisieren" Kleider:

xcrun atos -o /path/to/Conversion.app -arch arm64 -l 0x0??? 

Run wie die (natürlich mit einem geeigneten Wert für -l), kann ich Adressen wie 0x000694b5 eingeben und es so etwas wie -[ViewController viewDidLoad] + 128 ausspucken wird. Das Problem ist natürlich die Startadresse (der Wert der Option -l).

Wenn ich ein Crash-Protokoll habe, kann ich diese bekommen. Ich möchte jedoch ohne einen Unfall davonkommen.

Fragen:

Q1: Kann ich die Startadresse zur Laufzeit bestimmen und vielleicht ist es im Protokoll ausgegeben, so kann ich ihn an die ATOS -l Option?

EDIT: Es sieht so aus, wie dies möglich ist: (dank NSProgrammer für Antwort https://stackoverflow.com/a/12464678/1396265)

#import <mach-o/dyld.h> 

... 
intptr_t slide = _dyld_get_image_vmaddr_slide(0); 
const struct mach_header * load_addr = _dyld_get_image_header(0); 
NSLog(@"slide %lx load addr %lx", (long)slide, (long)load_addr); 

/EDIT

(wie ich in der Methodenaufrufe der Rahmen interessiert bin, sicher ich brauche Startadresse des Frameworks Die Startadresse der App ändert sich häufig (Randomisierung), ich weiß noch nicht, ob die Startadressen des Frameworks zufällig sind oder nicht.)

Q2: Gibt es andere Ansätze zur Untersuchung der Methoden im Call-Stack? (Breakpoints sind in meinem Szenario auch ziemlich ungeschickt.

)

EDIT:

Q3: Wie kann ich die Adressen des Frameworks symbolicate? Wo finde ich zum Beispiel den dSYM (oder was auch immer) für UIKit?

(Zum Beispiel habe ich etwas an. ~/Library/Developer/Xcode/iOS\ DeviceSupport/9.1\ \(13B143\)/Symbols/System/Library/Frameworks/UIKit.framework/ ich in mehr Details sehen würde hier.)

/EDIT

Vielleicht eine Lösung:

Eine Möglichkeit könnte sein, zu Speichern Sie die Protokollausgabe in einer Datei und führen Sie am Ende der Tests zu einem Absturz in der App. Auf diese Weise würde das Absturzprotokoll die Startadressen anzeigen und mit den Aufrufstapelinformationen aus den Protokollen könnte ich die callStackSymbols Ausgabe symbolisieren können. Ich werde das als nächstes versuchen.

+0

Es gibt ein paar Möglichkeiten, dies zu tun, wenn symbolicatecrash nicht funktioniert, einschließlich atos, dwarfdump und LLDB. Es gibt eine sehr schöne Zusammenfassung über einen vollständigen Symbolisierungsprozess [https://www.apteligent.com/developer-resources/symbolic-an-ios-crash-report/?partner_code=GDC_so_symbolicateios], der von einigen sein kann zusätzliche Hilfe – cjbeauchamp

Antwort

3

Das Hinzufügen von Protokollschnipsel zum Absturzprotokoll funktionierte bisher sehr gut, daher füge ich dies als Antwort vorerst hinzu. (Bessere Antworten sind auf jeden Fall willkommen :-))

Vorbereitungen:

callStackSymbols hinzufügen an den entsprechenden Stellen im Quellcode Anmeldung:

NSLog(@"call stack:\n%@", [NSThread callStackSymbols]); 

die App zum Absturz bringen (zum Beispiel, wenn ein bestimmter Bildschirm geöffnet ist):

strcpy(0, "000"); 

Redirect Logging Ausgabe in eine Datei:

FILE *logfile = freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr); 

Ausführung:

In Xcode läuft die App einmal, so wird es auf dem Gerät installiert und dann stoppen. Starten Sie dann die App direkt auf dem Gerät, damit Xcode den Absturz nicht abfangen kann.

Verwenden Sie die App, so dass der Call-Stack protokolliert wird (kann viele Male sein).

Schließlich die App zum Absturz (in meinem Fall, öffnen Sie einen bestimmten Bildschirm, der die schlechte strcpy aufruft).

bekommen die Dateien:

In Xcode öffnen "Fenster -> Geräte", wählen Sie das Gerät, wählen Sie die App und laden Sie die App Container, so dass die Log-Datei extrahiert werden kann.

Im selben Bildschirm öffnen Sie das Gerät Protokolle und exportieren Sie das Crash-Protokoll.

In Xcode öffnen Sie "Window -> Projects", wählen Sie das Projekt und zeigen Sie den abgeleiteten Datenordner im Finder (kleine Pfeiltaste rechts neben dem abgeleiteten Datenpfad). Navigieren Sie im abgeleiteten Datenordner zu "Build/Products/Debug-iphoneos /" und kopieren Sie MyApp.app und MyApp.app.dSYM.

Passen Sie die Crash-Protokoll:

Für mich ist es arbeitete Abschnitte zusätzliche Faden hinzufügen rechts vor „Binary Bilder:“. So finden Sie den Speicherort von "Binärbilder:". Fügen Sie eine Zeile "Thread 9999:" ein. Kopieren & das Call-Stack-Dumps einfügen und die führenden Leerzeichen Spalten entfernen, so dass es wie folgt aussieht:

2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree (
Thread 9999: 
0 MyApp        0x00000001001d95f8 -[MyClass myMethod:] + 100 
1 UIKit        0x000000018a5fc2ac <redacted> + 172 
2 UIKit        0x000000018a5d5ca4 <redacted> + 88 
3 UIKit        0x000000018a5d5b8c <redacted> + 460 
4 UIKit        0x000000018a5d5cc0 <redacted> + 116 
5 UIKit        0x000000018a5d5b8c <redacted> + 460 
6 UIKit        0x000000018a5d5cc0 <redacted> + 116 
7 UIKit        0x000000018a5d5b8c <redacted> + 460 
8 UIKit        0x000000018a8e85ac <redacted> + 460 
9 UIKit        0x000000018a5d4abc <redacted> + 96 
10 UIKit        0x000000018a935b7c <redacted> + 344 
11 UIKit        0x000000018a9306f8 <redacted> + 124 
12 UIKit        0x000000018aa584d8 <redacted> + 44 
13 UIKit        0x000000018a933d9c <redacted> + 188 
14 UIKit        0x000000018a70b668 <redacted> + 116 
15 UIKit        0x000000018a70b454 <redacted> + 252 
16 UIKit        0x000000018a70af38 <redacted> + 1404 
17 UIKit        0x000000018a70a9a8 <redacted> + 124 
18 UIKit        0x000000018a616d3c <redacted> + 312 
19 UIKit        0x000000018a616bc4 <redacted> + 108 
20 QuartzCore       0x0000000189dddc2c <redacted> + 284 
21 libdispatch.dylib     0x000000019a3a96a8 <redacted> + 16 
22 libdispatch.dylib     0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844 
23 CoreFoundation      0x00000001850001f8 <redacted> + 12 
24 CoreFoundation      0x0000000184ffe060 <redacted> + 1628 
25 CoreFoundation      0x0000000184f2cca0 CFRunLoopRunSpecific + 384 
26 GraphicsServices     0x000000018ff94088 GSEventRunModal + 180 
27 UIKit        0x000000018a644ffc UIApplicationMain + 204 
28 MyApp        0x0000000100093918 main + 124 
29 libdyld.dylib      0x000000019a3da8b8 <redacted> + 4 

Binary Images: 
... 

Die „Thread 9999:“ Linie macht das symbolicatecrash Skript die nächsten Zeilen symbolicate will. Ich wählte 9999, also weiß ich, dass dies meine hinzugefügten Abschnitte waren.

Run symbolication:

Finden Sie die symbolicatecrash Skript:

$ find /Applications/Xcode.app -name symbolicatecrash -type f 
/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash 
$ 

Der symbolication Befehl fast so geht:

$ symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

Sie müssen DEVELOPER_DIR setzen und fügen Sie den Pfad das Skript, so sieht es schließlich so aus:

$ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

Oder besser Sehvergnügen eingewickelt:

$ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' ... 
/Applications/Xcode.app/Contents/SharedFrameworks/ ... 
DTDeviceKitBase.framework/Versions/A/Resources/ ... 
symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

Das Ergebnis:

Die jetzt symbolicated Schnipsel wie folgt aussehen:

2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree (
Thread 9999: 
0 MyApp        0x00000001001d95f8 -[MyClass myMethod:] (MyFile.m:15) 
1 UIKit        0x000000018a5fc2ac -[UIScrollView _willMoveToWindow:] + 172 
2 UIKit        0x000000018a5d5ca4 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 88 
3 UIKit        0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 
4 UIKit        0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116 
5 UIKit        0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 
6 UIKit        0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116 
7 UIKit        0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 
8 UIKit        0x000000018a8e85ac __UIViewWillBeRemovedFromSuperview + 460 
9 UIKit        0x000000018a5d4abc -[UIView(Hierarchy) removeFromSuperview] + 96 
10 UIKit        0x000000018a935b7c __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke596 + 344 
11 UIKit        0x000000018a9306f8 -[UIPresentationController transitionDidFinish:] + 124 
12 UIKit        0x000000018aa584d8 -[_UICurrentContextPresentationController transitionDidFinish:] + 44 
13 UIKit        0x000000018a933d9c __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188 
14 UIKit        0x000000018a70b668 -[_UIViewControllerTransitionContext completeTransition:] + 116 
15 UIKit        0x000000018a70b454 -[UITransitionView notifyDidCompleteTransition:] + 252 
16 UIKit        0x000000018a70af38 -[UITransitionView _didCompleteTransition:] + 1404 
17 UIKit        0x000000018a70a9a8 -[UITransitionView _transitionDidStop:finished:] + 124 
18 UIKit        0x000000018a616d3c -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312 
19 UIKit        0x000000018a616bc4 -[UIViewAnimationState animationDidStop:finished:] + 108 
20 QuartzCore       0x0000000189dddc2c CA::Layer::run_animation_callbacks(void*) + 284 
21 libdispatch.dylib     0x000000019a3a96a8 _dispatch_client_callout + 16 
22 libdispatch.dylib     0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844 
23 CoreFoundation      0x00000001850001f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 
24 CoreFoundation      0x0000000184ffe060 __CFRunLoopRun + 1628 
25 CoreFoundation      0x0000000184f2cca0 CFRunLoopRunSpecific + 384 
26 GraphicsServices     0x000000018ff94088 GSEventRunModal + 180 
27 UIKit        0x000000018a644ffc UIApplicationMain + 204 
28 MyApp        0x0000000100093918 main (main.m:16) 
29 libdyld.dylib      0x000000019a3da8b8 <redacted> + 4 


Binary Images: 
... 

Wenn ich einen einfacheren Ansatz finden , das wird der Weg für mich sein. Es kann nützlich sein, ein Skript zu erstellen, das die Aufruf-Stacks aus der Protokolldatei zieht, die führenden Leerzeichen löscht und diese in das Crash-Protokoll einfügt.

+0

Das hat mich sehr nahe gebracht, aber ich habe nie die Symbolik zur Arbeit bekommen. Meine Lösung bestand darin, ein echtes Crash-Protokoll zu erstellen und den Inhalt eines Threads durch meinen manuellen Stack-Trace zu ersetzen. Das Ausführen von symbolicatecrash für diese Datei funktionierte – Miniroo

0

SYMBOLICATECRASH

Apple-Schiffe ein Skript mit XCode, die den symbolication Prozess eines Crash-Bericht in seiner Gesamtheit beschleunigt. Wenn Sie einen dSYM, Ihre App-Binärdatei und einen Absturzbericht haben, ist dies wahrscheinlich die einfachste Methode der Symbolisierung. Sie müssen sich um keine der Adressen kümmern - dieses Skript analysiert die gesamte Crash-Dump-Datei und verwendet ATOS, um alle Adressen in Symbole für Sie aufzulösen.

Suchen Sie die „symbolicatecrash“ auf Ihrem System:

cd /Applications/Xcode.app 
find . -name symbolicatecrash 

Export der DEVELOPER_DIR Umgebungsvariable, wenn es nicht

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer" 

Binärkopie Ihre .app vorhanden ist, die Crash-Bericht, und die .dSYM-Datei in einen temporären Ordner (z. B. ~/tmp). Führen Sie das Skript wie unser Beispiel unten:

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash -v ApteligentExampleApp.crash ApteligentExampleApp.app.dSYM/ 

Wenn alles gut geht, wird das Skript sollte Ihre gesamte Crash-Datei und Ausgabe das Ergebnis zu Ihrem Terminal-Fenster symbolicate.Dieses Skript macht nichts, was Sie nicht manuell mit ATOS oder einem anderen Tool tun könnten, aber es wird Ihnen viel schneller helfen.

Source

Verwandte Themen