Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Funktionsname herausfinden (https://www.delphipraxis.net/130511-funktionsname-herausfinden.html)

hitzi 9. Mär 2009 19:46


Funktionsname herausfinden
 
Hallo,

ist es irgendwie möglich den Funktionsnamen herauszufinden? So in der Art:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := Self.ClassName + ' ' + Self.???; //was muss statt den ??? hin damit in der Caption "TForm1 FormCreate" steht?
end;

Viele Grüße

generic 9. Mär 2009 19:48

Re: Funktionsname herausfinden
 
Nein, da alle Namen beim Compilieren entfernt werden.

Bevor hier einer Meckert:
Published Eigenschaften werden nicht entfernt.

hitzi 9. Mär 2009 19:51

Re: Funktionsname herausfinden
 
Schade. Danke für die Info :)

Bernhard Geyer 9. Mär 2009 19:53

Re: Funktionsname herausfinden
 
Doch. Ist möglich. Jedoch sind dazu TD32-Debuginfos und die Hilfe der JCL-Debug-Units nötig. Dann kannst du C-Like den Funktionsnamen/Stack/Zeilennumer etc. bekommen.

generic 9. Mär 2009 20:04

Re: Funktionsname herausfinden
 
Na gut - aber dafür wird eine Map-Datei benötigt (bei der JCL).

Bernhard Geyer 9. Mär 2009 20:07

Re: Funktionsname herausfinden
 
Zitat:

Zitat von generic
Na gut - aber dafür wird eine Map-Datei benötigt (bei der JCL).

Nichts bekommt man geschenkt. In einer managed Umgebebung bekommt man das zwar geschenkt auch ohne Extra Debug-Infos, aber dafür liegt der Quellcode offen.

hitzi 9. Mär 2009 21:07

Re: Funktionsname herausfinden
 
Auch dir vielen Dank Bernhard. Werd mir das Handling mal mit dieser Map Datei und JCL ansehen.

DMW 9. Mär 2009 23:18

Re: Funktionsname herausfinden
 
In C++Builder gibt es das __FUNC__-Makro, das den Namen der aktuellen Funktion als Stringkonstante enthält; vielleicht gibt es etwas Vergleichbares auch für Delphi?


Zitat:

Zitat von generic
Published Eigenschaften werden nicht entfernt.

Und da Event-Handler published sind, ist durchaus RTTI für FormCreate verfügbar ;)
Allerdings ist es praktisch unmöglich, eine beliebige Codeposition zweifelsfrei mit der Adresse der zugehörigen Funktion zu assoziieren, ohne über eine vollständige Funktionsliste zu verfügen, daher hilft das nichts.

Cyf 10. Mär 2009 00:43

Re: Funktionsname herausfinden
 
Zitat:

Zitat von generic
Allerdings ist es praktisch unmöglich, eine beliebige Codeposition zweifelsfrei mit der Adresse der zugehörigen Funktion zu assoziieren, ohne über eine vollständige Funktionsliste zu verfügen, daher hilft das nichts.

Das ist nicht ganz richtig, es funktioniert in manchen Fällen allerdings nicht allen.
Tatsächlich war das die erste Frage, die mir durch den Kopf ging, als ich das hier gelesen hab und ich musste es gleich mal ausprobieren. :wink:
Es hängt davon ab wie der Compiler den Code erstellt, der deine Funktion aufruft, wenn es ein call mit einem offset aus einem Register ist, ist es fast unmöglich, da nicht mehr klar ist, welchen Wert das Register hatte und der Wert auch nicht ohne einen Großteil des Codes davor erneut durchzugehen wiederhergestellt werden kann. Wenn es sich allerdings um einen call mit festem Offset handelt ($E8 + 4 byte signed integer in little endian), dann ist es ohne weiteres möglich den Einsprungspunkt der Funktion zurückzurechnen.
Ein Label in asm Code am Anfang der Funktion ist übrigens, falls jemand auf die Idee kommen sollte, auch wenig hilfreich, da (ausgenommen seien reine asm Routinen) der Compiler davor dazu neigt, eine unterschiedliche Länge von Befehle zur Erstellung eines stackframes einzufügen. Abgesehen davon ist das auch noch aufwendiger als ein @Funktionsname (wofür man den Namen angeben müsste und dann bei jeder Funktion anderen Code hat) und erfüllt ja nicht die Bedingung, dass das ganze für jede Funktion mit dem selben (möglichst einzeiligen) Befehl geht.

Aber imho ist es am sinnvollsten in solchen Protokoll-/Fehlermeldungen (oder für was braucht man das sonst?) einfach den Wert des EIP Registers einzufügen. Ist natürlich bei DLLs sinnlos und auch bei "normalen" PE nen gewisses Risiko, das nicht an die Standardadresse geladen wird, aber in 95% der Fälle sollte das eine hilfreiche Information (sogar genau wo's geknallt hat) sein.

Was das Zurückrechnen der Einsprungspunkte betrifft, scheint das nicht zu funktionieren, falls die aufrufende Funktion ein Event ist, das aus der Messageschleife ausgelöst wird, aber ich habs jetzt nicht mehr genau durchprobiert. :)

Bernhard Geyer 10. Mär 2009 07:18

Re: Funktionsname herausfinden
 
Zitat:

Zitat von DMW
In C++Builder gibt es das __FUNC__-Makro, das den Namen der aktuellen Funktion als Stringkonstante enthält; vielleicht gibt es etwas Vergleichbares auch für Delphi?

Ja. Wie schon geschrieben: JCL Debug-Units.

DMW 10. Mär 2009 14:35

Re: Funktionsname herausfinden
 
Zitat:

Zitat von Cyf
Zitat:

Zitat von generic
Allerdings ist es praktisch unmöglich, eine beliebige Codeposition zweifelsfrei mit der Adresse der zugehörigen Funktion zu assoziieren, ohne über eine vollständige Funktionsliste zu verfügen, daher hilft das nichts.

Das ist nicht ganz richtig, es funktioniert in manchen Fällen allerdings nicht allen.

Wieso ist es dann nicht ganz richtig? :gruebel:
Zitat:

Zitat von DMW
... praktisch unmöglich, eine beliebige Codeposition zweifelsfrei ...


Cyf 10. Mär 2009 16:52

Re: Funktionsname herausfinden
 
Ich halte es einfach nur nicht für praktisch unmöglich, jedoch in einigen Fällen für extrem aufwendig. :wink:
In den meisten ist es jedoch recht einfach. (Rücksprungaddresse auslesen und vor ihr den offset lesen)
Es ist so zumindest möglich, sich was zu bauen, was einem in den meisten Fällen mit wenig Aufwand den Funktionsnamen/Einsprungspunkt mitloggt (ansonsten "unbekannt") und ihn ergänzend mit dem EIP aufführt.

[Edit]Es müsste sogar immer möglich sein, wenn man Zugriffe auf die RTTI eines Objektes zulässt und dort den aktuellen EIP mit den Einsprungspunkten der Methoden vergleicht, die in der PE hintereinanderliegen sollten. Somit kommt man dann immer an den Einsprungspunkt, jedoch nur für Methoden, nicht für alle Funktionen. Außerdem sind die RTTI laut Hilfe versionsabhängig.

sirius 10. Mär 2009 17:31

Re: Funktionsname herausfinden
 
Die RTTI speichert nur das, was man auch über Methodaddress bekommt.

Cyf 10. Mär 2009 18:16

Re: Funktionsname herausfinden
 
Das Porblem ist mehr, dass man für Methodaddress den Metodennamen wissen muss. Methodaddress gibt den Einsprungspunkt zurück und um den geht es ja, ist also schon das Richtige. Das Problem ist also alle in der RTTI gespeicherten Einsprungspunkte durchzugehen und dann zu schauen, zwischen welchen der momentane EIP liegt.
Das müsste entweder über

Delphi-Quellcode:
GetTypeData(Self.ClassInfo);
und dann mit den Informationen weiter arbeiten gehen, oder über was anderes anderes aus TypInfo oder über manuelles durchforsten der RTTI gehen, wenn man denn den genauen Aufbau wüsste.
Die brauchbarste Information über die RTTI, die ich gefunden habe ist http://www.suite101.com/article.cfm/...gramming/64922 , allerdings schreib ich morgen nen LK und werde das heute nicht mehr weiter verfolgen.

Apollonius 10. Mär 2009 18:21

Re: Funktionsname herausfinden
 
Die nützlichste mir bekannte Quelle über RTTI in Delphi ist
Hallvard Vassbotns Blog. Dort sind alle Datenstrukturen, insbesondere die undokumentierten, aufgelistet. Die Methodeninformationen sind nicht dokumentiert und auch nicht bei ClassInfo verzeichnet, sondern an einem anderen Offset, nämlich System.vmtMethodTable.

DMW 10. Mär 2009 21:32

Re: Funktionsname herausfinden
 
Zitat:

Zitat von Cyf
[Edit]Es müsste sogar immer möglich sein, wenn man Zugriffe auf die RTTI eines Objektes zulässt und dort den aktuellen EIP mit den Einsprungspunkten der Methoden vergleicht, die in der PE hintereinanderliegen sollten. Somit kommt man dann immer an den Einsprungspunkt, jedoch nur für Methoden, nicht für alle Funktionen. Außerdem sind die RTTI laut Hilfe versionsabhängig.

Problematisch ist nur, daß du nicht wissen kannst, wo die Methode endet, sofern du nicht über eine vollständige Map-Datei verfügst.

(Für das Enumerieren der Methoden-RTTI einer Klasse hatte ich hier mal ein Beispiel gepostet, allerdings in C++.)

Felix015 11. Mär 2009 14:57

Re: Funktionsname herausfinden
 
mal so'ne frage wozu brauchst du das
?


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:50 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz