2013-08-07 3 views
10

Wenn ich einen Absturzbericht bekomme, sieht der störende Teil meines Codes manchmal so aus, anstatt mir die tatsächliche Zeilennummer anzuzeigen, obwohl der Absturzbericht symbolicated ist:Wie kann ich die Adresse eines Stack-Trace in LLDB für iOS finden

-[ViewController myMethod:] + 47 

um dies zu debuggen, muss ich wissen, welche Zeile von meinem Code dies so darstellt, dass ich es visuell überprüfen kann, um einen Haltepunkt setzen usw.

Was ist ein guter Weg um die Adresse einer Methode plus Offset, wie oben gezeigt, mit LLDB zu erhalten?

HINWEIS: Diese Frage ist kein Duplikat von how to read a crash report. Ich weiß, wie man einen Absturzbericht liest. Ich frage ganz speziell, wie man die entsprechende Zeile mit LLDB bekommt. Nichts in den anderen Antworten zeigt, wie man das macht. Sie sind ziemlich ausführlich und befassen sich mit allen möglichen Dingen im Umgang mit Absturzberichten und Debugging im Allgemeinen, zeigen aber nicht, was die einzelnen Schritte auf LLDB sind. Bitte duplizieren Sie diesen Fehler nicht.

+0

Ich bin dabei, Ihnen eine schreckliche Antwort zu geben, aber in engen Situationen durchführbar. Konvertiere diese Zahl in Dezimal, dividiere dann durch die Bus-Bits. Ich nenne das "die Anzahl der Anweisungszeilen, die ich durchqueren muss". Natürlich gibt es einen anderen Offset basierend darauf, was genau zwischen den Dingen gespeichert ist. Ich hatte 2020, endete als 128. Also im Grunde "einen Weg nach unten". Ich fand einen Bereich, der nicht richtig bewacht wurde, und es half mir im Grunde, meinen Absturz zu beheben. Guestimation –

Antwort

6

Hier ist etwas, was ich gefunden, die funktioniert:

Zuerst müssen Sie sich um die Adresse des Verfahrens zu finden.

image lookup -v -F "-[ViewController myMethod:]" 

im Ergebnis werden Sie eine Menge Infos sehen, aber der Bereich Teil geben Sie wollen Sie wollen

... range = [0x000708c0-0x00070c6c) ... 

(wo 0x000708c0 ist Adresse Methode)

Jetzt hinzufügen die von 47 angegebenen Offset, nur LLDB verwenden, dass Mathematik zu tun für Sie:

(lldb) p/x 0x000708c0 + 47 
(int) $0 = 0x000708ef 

und Sie Ihre Antwort erhalten, t er beleidigen Linie auf 0x000708ef

ist Oder noch besser, basierend auf Jason Molenda Antwort ist einfach direkt in die Codeliste zu gehen, die die Zeilennummer zeigen:

(lldb) source list -a `0x000708c0 + 47` 

EDIT: auf der verbesserten Basis Antwort von Jason Molenda

7

Ihre Schritte (image lookup + p/x addr + offset) geben Ihnen die rohe Adresse, wie Sie gefunden haben. Aber der ursprüngliche Absturzbericht enthielt wahrscheinlich eine Adresse vor der Methode + Offset --- es ist genauso einfach, Ihre Binärdatei mit target modules load an die richtige Adresse zu verschieben. Am Ende des Absturzberichtes sollte eine Liste der im Programm vorhandenen Binärbilder, einschließlich Ladeadresse und UUID, stehen.

Aber noch wichtiger ist, während die Adresse ist nett, was Sie wirklich suchen, ist der Quellort. In diesem Fall haben, wenn Sie die richtige Adresse für das Verfahren bestimmt (oder es an die entsprechende Adresse über target modules load geschoben), können Sie source list

(lldb) so l -a `addr + offset` 

verwenden Ich verwende die Graviszeichen Notation hier, die eine in tut -line Ausdruck Bewertung. Es gibt eine praktische Abkürzung für die meisten Befehle, die eine Adresse haben: Wenn Sie Leerzeichen weglassen, können Sie den Ausdruck ohne Backticks schreiben:

(lldb) so l -a addr+offset 

Sie auch image lookup mit einer Adresse verwenden können.Wenn Sie über Debug-Informationen verfügen, erhalten Sie an dieser Stelle Informationen zum aktuellen Standort der Variablen. Warum ist das nützlich? Da die meisten Absturzberichte den Registerkontext beim Absturz enthalten, werden Ihnen alle derzeit in einem Register enthaltenen Variablen zur Verfügung gestellt (-v ist erforderlich, um alle Registerstandortinformationen zu erhalten).

(lldb) im loo -v -a addr+offset 

Endlich - das wird nicht funktionieren, weil Sie mit einem Objective-C-Methode Namen zu tun hat - aber mit einem einfachen Namen C-Funktion können Sie in-line, so lange die Offset-Arithmetik als Sie übergeben den Funktionsnamen an einen Zeigertyp (es ist nicht zulässig, einem Funktionszeiger einen Offset hinzuzufügen). z.B.

(lldb) so l -a (char*)main+10 
+0

Wenn ich eine App in XCode ausführen, und diesen Befehl ausführen: im-loo -v -a $ pc Ich bekomme Ausgabe, die Variablen zeigt, aber ich sehe sowieso nicht, um diejenigen zu entsprechen, was in den Registern ist . Es listet ihre Position auf, aber nicht das, was registriert werden könnte. Variable: ID = {0x000000a4}, Name = "Selbst", type = "ViewController * const", Ort = DW_OP_fbreg (8), decl = ViewController.m: 30 so scheint ich keine zu bekommen "Ortungsinformationen registrieren". Mache ich etwas falsch? – Skotch

+1

Ah ja, die Standortbeschreibungen sind in der DWARF-Ausdrucksprache, ich habe vergessen, das zu erwähnen. "fbreg" bedeutet "frame base reg", lldb gibt dir einen "$ fp" -Register-Alias, der wahrscheinlich das Richtige ist. Wenn Sie einen 32-Bit-Prozess (Arm, Simulator) debuggen, würden Sie 'x/x $ fp + 8' machen - wenn Sie einen 64-Bit-Prozess (x86_64) debuggen, würden Sie' x/gx $ machen fp + 8', um den Wert zu sehen. "$ fp + 8" ist eine Adresse des Stapelspeichers, der "x" -Befehl (ein Alias ​​für "Speicherlesen") liest 4 Bytes ("x") oder 8 Bytes ("gx") des Speichers an dieser Adresse. –

+0

Da die Bildsuche nicht anzeigt, welche Variablen in Registern gespeichert sind, sollten wir den Kommentar zur Verwendung des Registerkontexts aus dem Absturzbericht entfernen. Vielleicht gibt es andere Möglichkeiten, das zu tun, aber das ist wirklich über den Rahmen der Frage hinaus. Stört es Sie, wenn ich Ihre Antwort bearbeiten, um diesen Teil zu entfernen? – Skotch

2

[beachten Sie funktioniert dies nur, wenn Sie Archiv in XCode aller baut Sie freigegeben speichern]

Informationen zuerst sammeln müssen:

  • APPNAME: den Kurznamen Ihre App im Archivverzeichnis (normalerweise der Name des XCode-Ziels; Sie sehen sie sofort, wenn Sie sich das Archivverzeichnis im Finder ansehen).
  • CRASHING_FUNCTION_NAME: Name der Funktion in nutzlosen Apfelbacktrace gezeigt (in dem Beispiel des OP, -[ViewController myMethod:])
  • ARCH: Architektur der Vorrichtung, die abgestürzt ist. Höchstwahrscheinlich ist der richtige Wert entweder armv7 oder arm64. Wenn Sie es nicht wissen, versuchen Sie beides.

hier Ok sind die Schritte:

  1. In XCode gehen Fenster ... Organizer ... Archiv
  2. Rechtsklick auf das Archiv für die Freigabe der Absturz Benutzer hat, und wählen Sie im Finder anzeigen
  3. eine Terminal-Shell öffnen und cd zu diesem Verzeichnis im Finder angezeigt
  4. führen Sie den folgenden in der Schale:

    lldb -arch ARCH Products/Applications/APPNAME.app/APPNAME 
    
  5. innen LLDB wie folgt vor:

    (lldb) add-dsym dSYMs/APPNAME.app.dSYM/Contents/Resources/DWARF/APPNAME 
    
    (lldb) disassemble --name CRASHING_FUNCTION_NAME 
    
  6. Sie jetzt eine reiche Demontage mit Symbolen sehen, und siehe da, zeigt jede Zeile die gleiche Dezimalverschiebung wie das Original nutzlos Apple-Backtrace (in der OPs Beispiel Offset nutzlos war 47), wie in:

    APPNAME[0xf4a7c] <+47>: ldr r0, [r0, r1] 
    
  7. Sie könnten in der Lage sein, die entsprechende Source-Leitung aus diesen Informationen, um herauszufinden, ob die Demontage eno hat Symbole, die dir helfen herauszufinden, wo du bist.

  8. wenn nicht, gibt es einen anderen großen Trick.Übergeben Sie die Adresse der Zeile, die abgestürzt:

    (lldb) image lookup -v --address 0xf4a7c 
    
  9. Jetzt lldb zeigt Ihnen eine reiche Sammlung von Informationen --- viel reicher als das, was von Apple Stapel Backtraces auch angezeigt, wenn sie enthalten Zeilennummern, und viel reicher als lldb source list --- über alle Quellzeilen, die zu der Assembler-Anweisung an dieser Adresse beigetragen haben. Achten Sie genau auf die Abschnitte Summary und LineEntry. Beispiel:

    Address: APPNAME[0x000f4a7c] (APPNAME.__TEXT.__text + 963740) 
    Summary: APPNAME`myclass::myfunc(bool, bool) + 904 [inlined] std::__1::deque<mystruct, std::__1::allocator<mystruct> >::operator[](unsigned long) + 22 at myfile.cpp:37945 
         APPNAME`myclass::myfunc(bool, bool) + 882 [inlined] myinlinefunc(int) + 14 at myfile.cpp:65498 
         APPNAME`myclass::myfunc(bool, bool) + 868 at myfile.cpp:65498 
    Module: file = "/Users/myuser/mydir/arch/Products/Applications/APPNAME.app/APPNAME", arch = "armv7" 
    CompileUnit: id = {0x000483a4}, file = "/Users/myuser/mydir/myfile.cpp", language = "objective-c++" 
    Function: id = {0x0045edde}, name = "myfunc", range = [0x000f46f4-0x000f572a) 
    FuncType: id = {0x0045edde}, decl = myfile.cpp:65291, compiler_type = "void (_Bool, _Bool)" 
    Blocks: id = {0x0045edde}, range = [0x000f46f4-0x000f572a) 
         id = {0x0045f7d8}, ranges = [0x000f4936-0x000f51c0)[0x000f544c-0x000f5566)[0x000f5570-0x000f5698) 
         id = {0x0046044c}, ranges = [0x000f49c6-0x000f49ce)[0x000f49d6-0x000f49d8)[0x000f4a2e-0x000f4a38)[0x000f4a58-0x000f4a82), name = "myinlinefunc", decl = myfile.cpp:37938, mangled = _Z11myinlinefunci, demangled = myinlinefunc(int) 
         id = {0x00460460}, ranges = [0x000f4a58-0x000f4a64)[0x000f4a66-0x000f4a82), name = "operator[]", decl = deque:1675, mangled = _ZNSt3__15dequeI12mystructNS_9allocatorIS1_EEEixEm, demangled = std::__1::deque<mystruct, std::__1::allocator<mystruct> >::operator[](unsigned long) 
    LineEntry: [0x000f4a7c-0x000f4a82): /Applications/Xcode7.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/deque:1678:14 
    Symbol: id = {0x00000805}, range = [0x000f46f4-0x000f572a), name="myclass::myfunc(bool, bool)", mangled="_ZN7myclass7myfuncEbb" 
    Variable: id = {0x00460459}, name = "myvar1", type = "int", location =  , decl = myfile.cpp:37938 
    Variable: id = {0x0045f7dd}, name = "myvar2", type = "bool", location = , decl = myfile.cpp:65583 
    Variable: id = {0x0045edf2}, name = "this", type = "myclass *", location = [sp+56], decl = 
    Variable: id = {0x0045ee01}, name = "myvar3", type = "bool", location = , decl = myfile.cpp:65291 
    Variable: id = {0x0045ee0e}, name = "myvar4", type = "bool", location = , decl = myfile.cpp:65292 
    
  10. In diesem Beispiel unter Summary, können wir sehen, dass die Linie, die eigentlich eine Kombination aus Code von myclass::myfunc(), myinlinefunc() und std::deque::operator[] abgestürzt war. Diese Art des Maischens ist sehr häufig für optimierten Code. Dies ist oft genug Information, um die problematische Quellzeile Ihres Codes zu finden. Unter LineEntry sehen wir die Zeilennummer für den am meisten verschachtelten Code, der zu dieser Assembler-Zeile beiträgt. In diesem Fall ist dies der STL-Code std::deque, in anderen Fällen jedoch möglicherweise die genaue Zeilennummer, die Sie in Ihrem Code haben möchten.

  11. Jetzt ist die einzige Frage: Warum auf der Erde Apple tut dies nicht nur für uns in der ursprünglichen Backtrace? Sie haben eindeutig all diese Informationen selbst! Warum lassen sie uns durch solche Reifen springen? Was verstecken sie?

Verwandte Themen