Wie extrahieren Sie lokale Variableninformationen (Adresse und Typ) aus einem Delphi-Programm oder den vom Compiler generierten Debug-Informationen?

105

Mein Ziel ist:

  • Angesichts eines angehaltenen Threads in einem von Delphi kompilierten 32- oder 64-Bit-Windows-Programm, um den Stapel zu durchlaufen (machbar)
  • Gegebene Stapeleinträge, um die lokalen Variablen in jeder Methode und ihre Werte aufzulisten. Das heißt, zumindest finden Sie ihre Adresse und ihren Typ (Ganzzahl 32/64 / signiert / vorzeichenlos, Zeichenfolge, Float, Datensatz, Klasse ...), deren Kombination verwendet werden kann, um ihren Wert zu ermitteln.

Das erste ist in Ordnung und es ist das zweite, um das es bei dieser Frage geht. Wie werden auf hoher Ebene lokale Variablen bei einem Stapeleintrag in Delphi aufgelistet?


Auf niedrigem Niveau habe ich Folgendes untersucht:

RTTI: Listet diese Art von Informationen zu Methoden nicht auf. Dies war nicht etwas, was ich jemals für eine realistische Option gehalten hätte, aber hier trotzdem aufzulisten.

Debug-Informationen: Laden der für einen Debug-Build erstellten Debug-Informationen .

  • Kartendateien: Selbst eine detaillierte Kartendatei (eine Datei im Textformat! Öffnen Sie eine und schauen Sie sie sich an) enthält keine lokalen Variableninformationen. Es ist im Grunde eine Liste von Adressen und Zeilennummern der Quelldatei. Hervorragend geeignet für die Korrelation von Adresse zu Datei und Zeile, z. B. die blauen Punkte in der Rinne. Nicht gut für detailliertere Informationen
  • Remote-Debugging-Informationen (RSM-Datei) - Keine bekannten Informationen zu Inhalt oder Format.
  • TD32 / TDS-Dateien: meine aktuelle Forschungsrichtung. Sie enthalten neben vielen anderen Informationen globale und lokale Symbole.

Die Probleme, auf die ich hier stoße, sind:

  • Es gibt keine Dokumentation des TD32-Dateiformats (die ich finden kann.)
  • Der größte Teil meines Wissens über sie stammt aus dem Jedi-JCL-Code, der sie verwendet (JclTD32.pas), und ich bin mir nicht sicher, wie ich diesen Code verwenden soll oder ob die Strukturen dort umfangreich genug sind, um lokale Variablen anzuzeigen. Ich bin mir ziemlich sicher, dass es mit globalen Symbolen umgehen wird, aber ich bin mir über lokale sehr unsicher. Es gibt eine Vielzahl von Konstanten definiert und ohne Dokumentation für das Format. Um zu lesen, was sie bedeuten, muss ich raten. Diese Konstanten und ihre Namen müssen jedoch von irgendwoher kommen.
  • Quelle, die ich mithilfe von TDS-Informationen finden kann, lädt oder verarbeitet keine lokalen Symbole.

Wenn dies der richtige Ansatz ist, lautet diese Frage: "Gibt es eine Dokumentation für das TDS / TD32-Dateiformat und gibt es Codebeispiele, die lokale Variablen laden?"

Ein Codebeispiel ist nicht unbedingt erforderlich, kann aber sehr nützlich sein, auch wenn es sehr minimal ist.

David
quelle
2
Ich habe die Jedi-JCL-Einheiten nicht verwendet, um auf TD32-Informationen zuzugreifen - ich habe meine eigene proprietäre Bibliothek dafür, aber es sieht so aus, als ob alle grundlegenden Installationsfunktionen, die Sie benötigen, in JclTD32.pas vorhanden sind. Es gibt jedoch keinen Demo-Code, den ich für den Zugriff auf die Variableninformationen finden kann, aber das Beispiel (in .. \ jcl \ examples \ windows \ debug \ sourceloc) zeigt, wie Zeilennummerninformationen aus TD32-Daten abgerufen werden Sie sollten in der Lage sein, darauf aufzubauen, um das zu erreichen, was Sie brauchen. Bitte melden Sie hier zurück, was Sie herausfinden :)
500 - Interner
2
@ 500-InternalServerError Danke. Zeilennummerninformationen sind einfach (sogar in Kartendateien) - können Sie jedoch Informationen zu den Angaben im JCL-Code bereitstellen, die sich speziell auf lokale Symbole beziehen? Was ist aus Neugier Ihre proprietäre TD32-Bibliothek und ist sie veröffentlicht / öffentlich verwendbar oder nur intern?
David
3
Jedes Prozedur- / Funktions- / Methodensymbol darunter enthält wiederum eine Liste lokaler Symbole. Die meisten Definitionen scheinen in der Jedi-Einheit vorhanden zu sein, aber einige sind auskommentiert. Mein Vorschlag wäre, winzige Test-Apps zu erstellen und zu prüfen, was eine Aufzählung von Symbolen zurückgibt. Der Code, den ich habe, ist urheberrechtlich geschützt und darf nicht veröffentlicht werden. Das Thema lokale Variablen wird sowieso nicht behandelt. Die Informationen, auf denen es basiert, sind jedoch halböffentlich, sodass ich möglicherweise helfen kann, wenn Sie auf bestimmte Wände stoßen.
500 - Interner Serverfehler
4
tds2pdb ( code.google.com/p/map2dbg ) scheint einen Parser für tds-Dateien zu haben. Es ist jedoch C # -Code.
Graymatter
4
Früher gab es ein informelles Dokument, aber dann entschied sich Borland (zu der Zeit), stattdessen eine DLL für den Zugriff auf die Debug-Informationen freizugeben, damit sie das interne Format ändern konnten und die Dokumentation nicht aktualisieren mussten. Leider kann ich momentan weder das Originaldokument noch die DLL finden. Ich schlage vor, dass Sie sich an den technischen Support von Embarcadero wenden und danach fragen.
500 - Interner

Antworten:

2

Überprüfen Sie, ob Debugging-Symbole nicht binär waren. Möglich ist auch die Verwendung von GDB (unter Windows ein Port davon). Es wäre großartig, wenn Sie eine .dbg- oder .dSYM-Datei finden würden. Sie enthalten Quellcode, z.

gdb> list foo
56 void foo()
57 {
58  bar();
59  sighandler_t fnc = signal(SIGHUP, SIG_IGN);
60  raise(SIGHUP);
61  signal(SIGHUP, fnc);
62  baz(fnc);
63 }

Wenn Sie keine Debugging-Dateien haben, können Sie versuchen, MinGW oder Cygwin abzurufen und nm (1) ( Manpage ) zu verwenden. Es werden Symbolnamen aus der Binärdatei gelesen. Sie können einige Typen enthalten, wie z. B. C ++:

int abc::def::Ghi::jkl(const std::string, int, const void*)

Vergessen Sie dann nicht, die --demangleOption hinzuzufügen, sonst erhalten Sie Folgendes:

__ZN11MRasterFont21getRasterForCharacterEh

anstatt:

MRasterFont::getRasterForCharacter(unsigned char)
Top Sekret
quelle
2
Jakub, danke für die Antwort. Leider muss ich wahrscheinlich ein bestimmtes Debug-Format lesen - TDS. Delphi-Apps werden unter Windows nicht mit GDB-kompatiblen Debug-Informationen kompiliert. Ich bin mir nicht sicher, wie nm helfen wird, da es auf einem bestimmten Debug-Dateiformat basiert, das wahrscheinlich nicht von Delphi generiert wird. Oder habe ich Ihre Antwort falsch verstanden - kann GDB zum Beispiel Delphis Symbole lesen?
David
@ DavidM, dein Kommentar ist sehr wichtig. Versuchen Sie, den Port von GNU Binutils oder GNU Debugger unter Windows zu finden (ich kenne nur den Port von Binutils). Es gibt eine BFD-Bibliothek für GDB. Es wird auch in Binutils verwendet. Es ermöglicht das Lesen mehrerer Dateiformate und das Erkennen dieser anhand ihrer magischen Zahlen. Wenn alles fehlschlägt, verwenden Sie das aufgerufene Tool strings. Es werden Zeichenfolgen aus jeder Binärdatei extrahiert. Siehe Manpage . Dies wird Zeichenfolgen drucken, die möglicherweise hilfreich sein müssen, aber nicht müssen
Top Sekret
0

Schauen Sie sich das http://download.xskernel.org/docs/file%20formats/omf/borland.txt Open Architecture Handbook an. Es ist alt, aber vielleicht finden Sie einige relevante Informationen über das Dateiformat.

Muetze1
quelle
Können Sie bitte einen Kontext hinzufügen, der Link könnte in Zukunft unterbrochen werden.
Hintham
Der Link enthält das offizielle Dokument aus Borland über das vom Borland-Compiler verwendete OMF-Dateiformat und andere von Borland verwendete binäre Dateiformate. Vor einigen Jahren habe ich mir das TDS-Dateiformat angesehen und es schien, dass einige Teile mit den dokumentierten Dateiformaten kompatibel sind. Wenn Sie versuchen, Informationen zu den lokalen Variablen aus der TDS-Datei zu sammeln, sollte die verknüpfte Dokumentation verwendet oder referenziert werden. Wenn der Link unterbrochen wird, ist meine Antwort nutzlos und die erforderlichen Informationen gehen verloren. Das verlinkte "Open Architecture Handbook" war Teil alter Turbo Pascal- und C-Versionen.
Muetze1