Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Procedur-Namen in einer Exception ausgeben ..


motion - Fr 26.08.05 17:08
Titel: Procedur-Namen in einer Exception ausgeben ..
Wie lässt sich bei einer Exception der Compiler dazu veranlassen, den Prozedur- oder Funktionsnamen hineinzucompilieren?

Delphi-Quelltext
1:
Raise Exception.CreateFmt('ungültiger Aufzählungstyp in Prozedur '+???,[]);                    



Moderiert von user profile iconChristian S.: Topic aus VCL (Visual Component Library) verschoben am Fr 26.08.2005 um 17:37


uall@ogc - Fr 26.08.05 17:12

nein das diese in der compilierten exe nicht mehr vorhanden sind (bzw. nicht mehr sein sollten)


BenBE - Fr 26.08.05 17:20

Das geht nur mit Zusatzsoftware wie Suche bei Google MADEXCEPT oder Suche bei Google EUREKALOG. Diese Software speichert sich Zusammen mit deiner EXE die Zeilen-Info-Daten und einige Bezeichner, wodurch die Prozeduren in denen ein Fehler auftrat ausgelesen werden können.


LigH - Fr 26.08.05 17:20

Wer sich so was selbst basteln wollte, könnte versuchen:

- globale String-Variable einführen
- am Anfang jeder Prozedur/Funktion vorherigen Stand zwischenspeichern und aktuellen Namen hineinspeichern
- am Ende jeder Prozedur/Funktion vorherigen Stand zurückspeichern

Macht aber bestimmt keinen Spaß. Wenn irgendwie möglich, besser an jeder riskanten Stelle einen eigenen try-except-Bereich verwenden und dort immer lokal sinnvolle Aktionen ausführen lassen. Oder mit Assertions arbeiten, wenn man riskante Zustände vorhersagen kann.


uall@ogc - Fr 26.08.05 17:22

DeDe bekommt auch die namen wieder raus, irgendwie müssten die da drin gespeichert sein nur wie weiß ich net oO
jedefalls die klassen-funktions-namen sind gespeichert


BenBE - Fr 26.08.05 17:52

Bei Klassen werden die Namen von published-deklarierten Methoden in der TypeInfo gespeichert.

Andere Programme arbeiten auch über die MAP-File, die man sich optional mit Delphi erzeugen kann. War heut erst wieder überrascht, was da alles drin steht ;-)


AXMD - Fr 26.08.05 17:57

user profile iconBenBE hat folgendes geschrieben:
Andere Programme arbeiten auch über die MAP-File, die man sich optional mit Delphi erzeugen kann. War heut erst wieder überrascht, was da alles drin steht ;-)


Wie kann man die auslesen? Kann man daraus etwa schließen, wo die Adresse einer AV hinzeigt :shock: - Weil Map... nur so ein Gedanke

AXMD


BenBE - Fr 26.08.05 18:23

@MAP-File: Dort stehen har klein nahezu alle zum Debuggen relevanten Offsets drinne. Diese muss man sich dann nur noch anhand des Modul-Handles umrechnen (in die Virtuellen Adressen und kann daraus dann schließen "Exception ist etwa in der Zeile aufgetreten", indem man einen Stacktrace vornimmt, der jegliche aufrufenden Routinen umfasst (oder die eigentliche Exception-Stelle, die im Exception-Objekt gespeichert ist).


AXMD - Fr 26.08.05 18:26

user profile iconBenBE hat folgendes geschrieben:
@MAP-File: Dort stehen har klein nahezu alle zum Debuggen relevanten Offsets drinne. Diese muss man sich dann nur noch anhand des Modul-Handles umrechnen (in die Virtuellen Adressen und kann daraus dann schließen "Exception ist etwa in der Zeile aufgetreten", indem man einen Stacktrace vornimmt, der jegliche aufrufenden Routinen umfasst (oder die eigentliche Exception-Stelle, die im Exception-Objekt gespeichert ist).


Hieße das (umgesetzt), dass man bei einer AV 123456 an Adresse 7890AB sagen könnte, dass sie etwa in Zeile XY aufgetreten ist? Wieviel Aufwand ist das?

AXMD


motion - Fr 26.08.05 19:36

Uiiih,
doch eine vielzahl von Ideen und Beteiligung an meinem Thread. Vielen Dank dafür.
Hmmm, ich hatte ja gehofft, das es doch eine Compiler- oder Systemvariable gibt, die man verwenden kann.
Ist dann leider doch nicht so einfach. Also muss ich es dann doch selbst als Konstante bei jedem Vorkommen einsetzen.


AXMD - Fr 26.08.05 19:56

user profile iconmotion hat folgendes geschrieben:
Uiiih,
doch eine vielzahl von Ideen und Beteiligung an meinem Thread. Vielen Dank dafür.
Hmmm, ich hatte ja gehofft, das es doch eine Compiler- oder Systemvariable gibt, die man verwenden kann.
Ist dann leider doch nicht so einfach. Also muss ich es dann doch selbst als Konstante bei jedem Vorkommen einsetzen.


Weniger aufwändig sind oben angesprochene Tools wie madexcept

AXMD


BenBE - Fr 26.08.05 20:06

Ist nicht kompliziert. Die Map-File zu parsen ist relativ einfach. Aus dieser kann man über relativ einfache Berechnungen auf die eigentliche Exception-Adrese schließen. Daraus die Zeilennummer zu ermitteln ist nur ne Sache von wenigen Programmzeilen ...


retnyg - Fr 26.08.05 20:35

user profile iconBenBE hat folgendes geschrieben:
dieser kann man über relativ einfache Berechnungen auf die eigentliche Exception-Adrese schließen. Daraus die Zeilennummer zu ermitteln ist nur ne Sache von wenigen Programmzeilen ...

dann sollte es für dich ja kein problem sein die paar zeilen hier zu posten, oder ?


BenBE - Fr 26.08.05 20:50

Fertigen Source zum Direkteinbau hab ich ATM nicht da, werd mir aber für eigengebrauch im Zusammenhang mit Omorphia [http://www.omorphia.de/] demnächst mal eine Unit schreiben. Guckt euch dazu doch einfach mal eine MAP-Datei von Delphi mit Notepad an ... Dann sollte eigentlich klar sein, wie das mit dem Auslesen geht ...


AXMD - Fr 26.08.05 21:21

user profile iconretnyg hat folgendes geschrieben:
user profile iconBenBE hat folgendes geschrieben:
dieser kann man über relativ einfache Berechnungen auf die eigentliche Exception-Adrese schließen. Daraus die Zeilennummer zu ermitteln ist nur ne Sache von wenigen Programmzeilen ...

dann sollte es für dich ja kein problem sein die paar zeilen hier zu posten, oder ?


[OT]Eine Zeilennummernberechnung wär mal was für die Leute, die Betriebssysteme, Bootloader, Shells etc. schreiben wollen :mrgreen: Weil sowas wär wirklich nice to have - weil dann kann man mit Betastestermeldungen, die mit AVs zu tun haben, endlich mehr anfangen :)[/OT]

AXMD


BenBE - So 28.08.05 13:29

Hab mal eine erste kleine Test-Unit fertig...

Liest bis jetzt Unit-Namen und Zeilennummern. Das Publics-Segment der MAP-File wird noch nicht geparst, das kommt aber später für Omorphia noch in die Unit mit rein (später erhältlich unter ODbgMapfile.pas [http://viewcvs.omorphia.de/omorphia/library/ODbgMapfile.pas]).

Zur Zeit sieht ein Stacktrace mit Debug-DCUs und voller MAP-File bei mir so aus:

Stacktrace mit detaillierter Mapfile und Debug-DCUs:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
0045F4B1@Linenumber.exe\Unit1(00422)
00437B0C@Linenumber.exe\Controls(04706)
0042E974@Linenumber.exe\StdCtrls(03473)
0042EADB@Linenumber.exe\StdCtrls(03525)
004378DE@Linenumber.exe\Controls(04646)
0043B45B@Linenumber.exe\Controls(06343)
0042E7C3@Linenumber.exe\StdCtrls(03415)
004375E9@Linenumber.exe\Controls(04553)
0043B61D@Linenumber.exe\Controls(06388)
0043BDFA@Linenumber.exe\Controls(06574)
004572ED@Linenumber.exe\Forms(04117)
004378DE@Linenumber.exe\Controls(04646)
0043B45B@Linenumber.exe\Controls(06343)
00454AF9@Linenumber.exe\Forms(03099)
0043B02B@Linenumber.exe\Controls(06237)
0041DA0E@Linenumber.exe\Classes(10967)
77E3158F@user32.dll\???(?????)
77E2AFA1@user32.dll\???(?????)
77E2AFC7@user32.dll\???(?????)
717521F0@comctl32.dll\???(?????)
7175276F@comctl32.dll\???(?????)
71752574@comctl32.dll\???(?????)
7172C11B@comctl32.dll\???(?????)
7175276F@comctl32.dll\???(?????)
71752643@comctl32.dll\???(?????)
77E3158F@user32.dll\???(?????)
77E2B7A9@user32.dll\???(?????)
77E2B811@user32.dll\???(?????)
77E28126@user32.dll\???(?????)
77E17AE2@user32.dll\???(?????)
77E3158F@user32.dll\???(?????)
77E2AFA1@user32.dll\???(?????)
77E17E2D@user32.dll\???(?????)
0043B5A1@Linenumber.exe\Controls(06369)
0043CE9E@Linenumber.exe\Controls(07091)
004378DE@Linenumber.exe\Controls(04646)
0043B45B@Linenumber.exe\Controls(06343)
0042E7C3@Linenumber.exe\StdCtrls(03415)
0043B02B@Linenumber.exe\Controls(06237)
0041DA0E@Linenumber.exe\Classes(10967)
77E3158F@user32.dll\???(?????)
77E31DC9@user32.dll\???(?????)
77E17ED6@user32.dll\???(?????)
0045C63C@Linenumber.exe\Forms(06892)
0045C8D7@Linenumber.exe\Forms(06976)
0045F77C@Linenumber.exe\Linenumber(00013)
77E98989@kernel32.dll\???(?????)
00000000@Linenumber.exe\System(?????)


Testprojekt mit besagter Unit siehe Anhang.

WICHTIG: Damit das Programm DebugInfos findet muss die MAP-File ATM im Arbeitsverzeichnis der EXE liegen. Zusätzliche MAP-Files für Zusatz-DLLs werden automatisch erkannt, wenn diese DLLname.map heißen und auch im Arbeitsverzeichnis liegen.

HINWEIS: Mapfile-Parser bisher nur mit D7 getestet. Für andere Compiler kann es notwendig sein, den Parser leicht abzuändern.

ACHTUNG: Bei Verwendung in eigenen Programmen bitte Credits halten und meinen Namen oder Projekt Omorphia sichtbar in der Aboutbox oder Readme erwähnen. Unit steht unter LGPL!


BenBE - So 28.08.05 14:19

Kleine Sache noch: user profile iconuall@ogc wies mich grad auf nen Fehler in dem Demo hin, was zwar nix mit der eigentlichen Adress-Umsetzung zu tun hat, aber dennoch unschöne Effekte erzeugt ;-)

Die Button1Click-Methode muss folgendermaßen abgeändert werden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
Procedure TForm1.Button1Click(Sender: TObject);
Label
    Test;
Var
    X: Pointer;
Begin  
    Memo1.Lines.BeginUpdate;
    try
    Memo1.Lines.Clear;

Test:
    Asm
    MOV     EAX, OFFSET [Test]
    MOV     DWORD PTR [X], EAX    
    End;

    Caption := AddressToLocation(X);

    GetDetailedStackTrace(Memo1.Lines, 100);
    finally
        Memo1.Lines.EndUpdate;
    End;
End;


Ich arbeite mit uall noch an einer etwas verbesserten Version zusammen, da noch einige Unstable SourceFragments enthalten sind ;-) Neuer DL folgt soweit die Unit vollständig stäble ist ...

Die eingebundene INC-File von Omorphia wird ATM noch nicht zwingend benötigt; dient einzig der Compiler- und Platform-Erkennung.


worm - So 28.08.05 15:43

user profile iconAXMD hat folgendes geschrieben:
Hieße das (umgesetzt), dass man bei einer AV 123456 an Adresse 7890AB sagen könnte, dass sie etwa in Zeile XY aufgetreten ist?
Wenn Du mit Delphi arbeitest, kannst Du dann nicht einfach 'Suchen' -> 'Laufzeitfehler suchen...' nutzen? :gruebel:


BenBE - So 28.08.05 15:50

user profile iconworm hat folgendes geschrieben:
user profile iconAXMD hat folgendes geschrieben:
Hieße das (umgesetzt), dass man bei einer AV 123456 an Adresse 7890AB sagen könnte, dass sie etwa in Zeile XY aufgetreten ist?
Wenn Du mit Delphi arbeitest, kannst Du dann nicht einfach 'Suchen' -> 'Laufzeitfehler suchen...' nutzen? :gruebel:


Jain. Die Funktion "Laufzeitfehler suchen" funktioniert nur dann, wenn die EXE aus dem Source der IDE generiert wurde und der Source seit dem nichtmehr verändert wurde. Oftmals ist man aber schon einige Schritte weiter, so dass Source und EXE nicht mehr zusammenpassen. AV-Adressen sind dann sinnlos. Da hilft dann schon eher eine Mapfile, wie sie von Delphi generiert wird. Dort stehen alle wichtigen Infos drin, die man brauch. Selbst, wenn man schon tausende Zeilen Source weiter ist, stimmt die Mapfile (zur jeweiligen EXE-Version). Nun brauch man nur noch die Adresse dort nachschlagen und erhält die Source-Stelle. Nix anderes macht mein Demo ...

Achso, da wir hier ungeduldige User zu haben scheinen: Die DEMO braucht etwa 1-2 Minuten für den Stacktrace. Also: Geduldig sein!!!


BenBE - Mo 29.08.05 14:46

Ich hab auf das CVS-Repo [http://viewcvs.omorphia.de/] von Projekt Omorphia [http://www.omorphia.de/] mal eine um einiges optimierte und erweiterte Version der Unit ODbgMapfile.pas [http://viewcvs.omorphia.de/omorphia/library/source/ODbgMapfile.pas] hochgeladen ... Diese beherrscht inzwischen selbst mit UPX oder neolite komprimierte EXE-Dateien.

In Zusammenarbeit mit der ODbgInterface.pas [http://viewcvs.omorphia.de/omorphia/library/source/ODbgInterface.pas], die zum Ausführen einiger Teilfunktionen benötigt wird, werden nun automatisch auf die Debug-Console (Ereignisprotokoll von Delphi) jegliche Exceptions ausführlich ausgegeben. Diese können wenn nötig sogar programm-intern weiterverarbeitet werden.

In diesem Zusammenhang noch mal einen herzlichen Dank an user profile iconuall@ogc wegen den Tests und Optimierungen für die System-Interna ...