2009-06-26 4 views
13

Ich habe eine C-Anwendung, die wir auf einer Kundenseite bereitgestellt haben. Es wurde kompiliert und läuft auf HP-UX. Der Benutzer hat einen Absturz gemeldet und wir haben einen Core Dump erhalten. Bis jetzt konnte ich den Absturz nicht im Haus duplizieren.Debug Core-Datei ohne Symbole

Wie Sie vermuten würden, enthält die Core File/Deployed Executable keinerlei Symbole. Wenn ich es in GDB laden und eine bt tun, das Beste, was ich bekomme, ist dies:

(gdb) bt 
#0 0xc0199470 in ??() 

Ich kann auf der Datei einen ‚Strings Kern‘ tun, aber mein Verständnis ist, dass alles, was ich dort ist alles Strings in der ausführbaren Datei, so scheint es fast unmöglich, dort etwas zu finden.

Ich habe eine Debug-Version (kompiliert mit -g) der ausführbaren Datei, die leider ein paar Monate neuer als die veröffentlichte Version ist. Wenn ich versuche, mit dieser Nabe gdb zu starten, sehe ich dies:

warning: exec file is newer than core file. 
Core was generated by `program_name'. 
Program terminated with signal 11, Segmentation fault. 
__dld_list is not valid according to __dld_flags. 

#0 0xc0199470 in ??() 
(gdb) bt 
#0 0xc0199470 in ??() 

Während es möglich wäre, eine Debug-Version zu kompilieren und es am Standort des Kunden zu implementieren und dann für einen weiteren Absturz warten, wäre es relativ schwierig sein, und aus einer Anzahl von Gründen unerwünscht.

Ich bin ziemlich vertraut mit dem Code und habe eine relativ gute Vorstellung davon, wo im Code es stürzt basierend auf dem Fehlerbericht des Kunden.

Gibt es irgendeine Möglichkeit, weitere Informationen von diesem Core Dump zu erhalten? Über Strings oder einen anderen Debugger oder irgendetwas? Vielen Dank.

Antwort

7

Diese Art von Antwort von GDB:

(gdb) bt 
#0 0xc0199470 in ??() 

kann auch in dem Fall vorkommen, daß der Stapel durch einen Puffer zertrümmert wurde überschwemmt, wobei die Rücksprungadresse in Speicher überschrieben wird, so wird der Programmzähler eingestellt wird ein scheinbar zufälliger Bereich.

Dies ist eine der Möglichkeiten, dass selbst ein Build mit einer entsprechenden Symboldatenbank einen Symbolsuchfehler (oder seltsam aussehende Backtraces) verursachen kann. Wenn Sie dies immer noch erhalten, nachdem Sie die Symboltabelle haben, ist Ihr Problem wahrscheinlich, dass die Daten Ihres Kunden einige Probleme mit Ihrem Code verursachen.

+0

Diese Antwort scheint mir lächerlich wahrscheinlich. Ich werde auf jeden Fall den Code für potentiell überlaufene Bereiche durchsehen. – Morinar

+0

Wenn das Debuggen mit einer "Duplikatkopie" nichts anzeigt, ist es an der Zeit, Register- und Stack-Dumps zu betrachten, um herauszufinden, wie Sie in die Mitte von Nirgendwo gelangt sind. Es kann auch ein fehlerhafter (oder nicht initialisierter) Funktionszeiger, eine Zuordnungsüberschreitung oder möglicherweise eine falsche Puffergröße oder eine "schlechte" Eingabe sein, die einen Puffer durchbrennt (unter Verwendung von sprintf()/sscanf mit unkontrollierter Eingabe usw.). – jesup

+0

Ich habe hier noch nie etwas herausgefunden, aber ich akzeptiere das, da es immer noch am wahrscheinlichsten ist. – Morinar

1

Haben Sie die genaue Quelle, die Sie verwendet haben, um die alte Version zu kompilieren (zB durch ein Tag im Quellbaum oder so ähnlich)? Vielleicht könntest du damit wieder aufbauen und vielleicht einen Einblick bekommen, wo der Absturz stattgefunden hat?

+0

Ich habe die genaue Quelle, aber dieses bestimmte Stück Code hat sich nicht viel (wenn überhaupt) von diesem Punkt zu dem geändert, was ich jetzt habe. – Morinar

0

Hier gibt es nicht viele Informationen. Die Binärdatei wird entfernt. Wenn Sie jedoch den Segmentierungsfehler betrachten, sollten Sie nach Stellen suchen, wo die Möglichkeit besteht, dass Sie ein Stück Speicher überschreiben.

Dies ist nur ein Vorschlag. Es kann viele Probleme geben.

BTW, wenn Sie nicht in der Lage sind, in Ihrem lokalen Computer zu reproduzieren, dann könnte die Datenmenge auf Kunden 'ein Problem sein.

5

Für die Zukunft:

  1. Vergewissern Sie sich, dass Sie immer mit einer externen Symbole Datenbank aufzubauen (das Build kein Debug ist - es ist ein Release-Build ist, aber Sie speichern die Symboltabelle separat)
  2. halten es um für die Versionen bereitstellen Sie

für diese Situation:

Sie kennen den allgemeinen Bereich, so zu sehen, ob Sie richtig sind, gehen Sie auf den Stapel tra ce und finde den Assembler-Code - achte darauf und schau, ob du denkst, dass er mit deiner Quelle übereinstimmt (das ist einfacher, wenn du eine Idee hast, welche Quelle diese Assembly erzeugt hat). Wenn es richtig aussieht, haben Sie eine Überprüfung Ihrer Hypothese. Sie können möglicherweise die Werte der lokalen Variablen herausfinden, indem Sie auf den Stack schauen (da Sie wissen, was Sie übergeben und deklariert haben).

+0

Wie finde ich den Assembly-Code und/oder komme zum Stack-Trace? Alle Stack-Spuren, die ich bisher gesehen habe, habe ich oben eingefügt ... – Morinar

+0

Der Befehl ist 'disassemble' - siehe http://www.unknownroad.com/rtfm/gdbtut/gdbadvanced.html –

+0

Ich tat dies und bekam: (gdb) zerlegen Keine Funktion enthält Programmzähler für ausgewählte Rahmen. Das scheint mir, als ob es den zerschmetterten Stapel bevorzugt, wie von Sufian unten vorgeschlagen. – Morinar

2
  1. Immer Verwendung der Quellcodeverwaltung (CVS/GIT/Subversion/etc), auch für Test-Releases
  2. Tag alle Mitteilungen
  3. (in Zukunft) Betrachten Sie einen Build mit Debugging machen (- g) und strippen Sie die ausführbare Datei vor dem Versand. HINWEIS: Erstelle keine zwei Builds mit und ohne -g; sie können nicht übereinstimmen, da -g gelegentlich verursachen kann, dass ein anderer Code selbst bei der gleichen Optimierungsstufe erzeugt wird. In super-performance-critical Code können Sie auf das -g für kritische Dateien verzichten - am meisten wird es keinen Unterschied machen.
  4. Wenn Sie wirklich steckengeblieben sind, werfen Sie den Stapel ab und legen Sie relevante Teile des Heaps auf hex ab und schauen Sie es von Hand an; vielleicht eine instrumentierte Kopie nehmen und nach ähnlichen "Signaturen" im generierten Code und auf dem Stack suchen. Dies ist echte „old-school“ Debugging ... :-)
+0

Definitiv solide Beratung. Wir machen die Schritte 1-3 hier, aber egal, sie werden von einer völlig anderen Gruppe von Leuten (wir haben ein Team, das für diese Dinge verantwortlich ist) behandelt als ich. – Morinar

3

Unter gdb „Info-Register“ sollten Ihnen genug von dem Ausführungszustand zum Zeitpunkt des Absturzes gibt mit einer Demontage zu verwenden, von die ausführbare und und relevante gemeinsame Bibliotheken. Normalerweise verwende ich objdump, um die Ausgabe zu disassemblieren, die Ausgabe in eine Datei umzuleiten und dann die Datei in meinem Lieblingseditor aufzurufen - das ist nützlich, um Notizen zu behalten, wenn die Dinge herausgefunden werden. Auch gdbs "info target" und "info sharedlib" können nützlich sein, um herauszufinden, wo geteilte Bibliotheken geladen sind.

Mit Registerstatus, Stapelinhalt und Disassemblierung in der Hand mit ein wenig Glück sollte es einfach (wenn langweilig) sein, den Aufrufstapel zu rekonstruieren (es sei denn, der Stapel wurde durch einen Pufferüberlauf oder Ähnliches zerstört) Katastrophe ... könnte in diesem Fall ein Ouija-Brett oder eine Kristallkugel benötigen.)

Sie könnten auch in der Lage sein, eine Disassemblierung der neueren Version, die mit -g erstellt wurde, mit der Disassemblierung der entfernten Version zu korrelieren.

1

Versuchen Sie eine "Pmap" gegen die Core-Datei (wenn HP/UX dieses Tool hat). Dies sollte die Startadressen aller Module in der Core-Datei melden. Mit dieser Information sollten Sie in der Lage sein, die Adresse der Fehlerstelle zu ermitteln und herauszufinden, welche Bibliothek abgestürzt ist. Ein weiterer Adressenvergleich zwischen der Crash-Adresse und den Adressen der bekannten Funktionen in der Bibliothek ("nm" gegen die Bibliothek sollte das bekommen) kann Ihnen helfen festzustellen, welche Funktion abgestürzt ist.

Selbst wenn Sie es schaffen, die Funktion an der Spitze des Stapels zu identifizieren, ist es nicht sehr wahrscheinlich, dass diese Funktion die Ursache des Problems ist ... hoffentlich ist es tatsächlich in Ihrem Code abgestürzt und nicht sagen wir , die Standard-C-String-Bibliothek. Die Neuanlage des Stack-Trace ist das nächstbeste an diesem Punkt.

0

Ich glaube nicht, dass die Kerndatei Symbole enthalten soll. Sie müssen in der Lage sein, eine Version Ihres Programms zu erstellen, das genau das gleiche ist als was Sie an Ihren Kunden geliefert, aber mit -g.Wenn Sie die ausführbare Debug-Datei entfernen, sollte sie mit der ausgelieferten Version identisch sein. Nur dann kann gdb dir etwas Nützliches geben.