Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Exception - Register + DataStack (https://www.delphipraxis.net/210611-exception-register-datastack.html)

Stevie 23. Mai 2022 22:25

AW: Exception - Register + DataStack
 
Zitat:

Zitat von himitsu (Beitrag 1506272)
Das stimmt so weit auch, denn nicht "RaiseLastOSError" löst die Exception aus, sondern das passiert ja eh erst später, weiter drinnen.

Ja, genau wie beim Code im Eingangspost! :roll:

himitsu 24. Mai 2022 07:45

AW: Exception - Register + DataStack
 
Wenn man mit richtigen Delphi-Exceptions arbeitet, dann erstellt man ja oft auch erst kurz vorher noch das Exception-Object
und beim Erstellen eines Objektes und dem zusammenbauen von Strings, läuft genug ab, um Alles zu verändern.

Ausnahme, man macht es wie beim EOutOfMemory, wo das Objekt bereits vorher erstellt wurde (klar, weil ja praktisch der RAM schon voll ist und kein Speicher mehr zum Erstellen frei sein könnte)
und braucht dann "nur" noch das
Delphi-Quellcode:
Raise
, womit aber dennoch mindestens ein EAX verändert wird, um das Objekt zu übergeben.



Bleiben also nur noch die OS-Exceptions, wie AccessViolation oder DivisionByZero, was man nahezu direkt auslösen könnte.
Beim Letztem wird zwar oft auch mit mindestens einem Wert in den Registern gerechnet, aber da könnte man "irgendwas" nehmen, war grade in den Registern steht und die NULL kommt vom Heap/Stack.

Aber auch hier wieder das Problem, dass im ExceptionRecord von Windows keine Register drin sind und man somit auch erst wieder Code in der Fehlerbehandlung braucht, um die Register auszulesen,
was nur ginge, wenn das in einem anderen Thread passiert.

Delphi-Quellcode:
  EExternal = class(Exception)
  public
    {$IFDEF MSWINDOWS}
    ExceptionRecord: PExceptionRecord platform; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
    {$ENDIF}
    {$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
    ExceptionAddress: LongWord platform;
    AccessAddress: LongWord platform;
    SignalNumber: Integer platform;
    {$ENDIF}
  end;

  EExternalException = class(EExternal);

  EIntError = class(EExternal);
  EDivByZero = class(EIntError);
  ERangeError = class(EIntError);
  EIntOverflow = class(EIntError);

  EMathError = class(EExternal);
  EInvalidOp = class(EMathError);
  EZeroDivide = class(EMathError);
  EOverflow = class(EMathError);
  EUnderflow = class(EMathError);

  EAccessViolation = class(EExternal); <<<<<<<<<<<<<
  EPrivilege = class(EExternal);
  EStackOverflow = class(EExternal) end deprecated;
  EControlC = class(EExternal);
Delphi-Quellcode:
  try
    ...
    Pointer(nil) := 666;
  except
    on E: Exception do begin
      // für GetThreadContext wäre es hier schon zu spät
      // aber E.ExceptionRecord wäre aber noch verfügbar
    end;
  end;
Noch etwas früher kommt man in die Fehlerbehandlung rein, wenn man die Registrierungsstellen in Exception/SysUtils/System benutzt,
aber auch da wird vorher immer noch etwas Code ausgeführt.

Sinspin 24. Mai 2022 10:31

AW: Exception - Register + DataStack
 
Ich verweise mal ganz dezent auf INT 3, der als Debugger Interrupt bekannt ist. Damit bekommt man eigentlich am sichersten die Werte in den Registern. Die Frage ist nur wie man ihn auslößt wenn man einen Fehler erkennt und wie dann ein Debugger reagiert um die infos anzuzeigen. In meinem Fall war immer Delphi offen und stoppte unerwünschterweise in einer Win DLL.

himitsu 24. Mai 2022 10:44

AW: Exception - Register + DataStack
 
Delphi-Quellcode:
asm int 3 end;
oder MSDN-Library durchsuchenDebugBreak; als Befehl. Ersteres geht nur in Win32, da der Win64-Compiler kein InlineAssembler mehr unterstützt. :cry:
Es muß dann aber ein Debugger am Programm hängen. (ein Programm kann sich aber auch selbst bei sich selbst als Debugger registrieren/anhängen).

Hängt kein Debugger am Programm, dann raucht INT 3 ab und Windows beendet das Programm.

Gruber_Hans_12345 25. Mai 2022 06:56

AW: Exception - Register + DataStack
 
Ok mal danke für die Infos.

dh. wenn du würde es nur gehen, wenn eine zeite EXE (der Debugger) oder der Debugger im eigenen Programm in nem Thread aktiv ist.

Hat schon mal irgendwer einen primitiven Debugger in delphi gemacht?
dh. Es würde dann dann auch automatisch die Exceptions im Debugger ankommen, zu einem Zeitpunkt wo noch kein weiterer Code ausgeführt wurde, und alle Register und Stack sachen sauber sind?

Was wäre da der Grund warum das nicht jede ExceptionHandling Routine macht? - wäre doch dann viel klüger?

himitsu 25. Mai 2022 08:19

AW: Exception - Register + DataStack
 
INT 3 triggert den angehängten Debugger (hängt kein Debugger dran, raut der Interuppt ab und das Programm wird beendet).
Der Debugger oder jeder Andere kann von einem anderem Thread/Prozess aus problemlos die Register auslesen, da der dort ablaufende Code keinen Einfluß auf die eigentlichen Register hat (der hat ja seine eigenen Register/ThreadContext, in dem er arbeitet)

Bei einer Fehlerbehandlung im eigenen Thread, wird dort Code ausgeführt, was die Register unweigerlich verändert.
Die einzige Lösung wäre gewesen, wenn Windows bei der Behandlung die Register in den ExceptionRecord kopieren täte, dann hätte man in der eigenen Fehlerbehandlung später Zugriff auf diese Kopie gehabt.
Wenn man also z.B. von in einem anderen Thread seine Fehlerbehandlung einbaut, sich dann von da als Debugger bei seinem eigenem Prozess dranhängt, dann hat han die Fehlerbehandlung in einem anderen Thread, von wo aus man drüben die Register auslesen kann, bevor dort weitergearbeitet wird.
Im Gegensatz zu den normalen Debuggern darf man natürlich nicht die anderen Threads anhalten (wenn man auf die Exception reagiert), bzw. zumindestens nicht sich selbst.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:07 Uhr.
Seite 2 von 2     12   

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