Delphi-PRAXiS
Seite 1 von 2  1 2      

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)

Gruber_Hans_12345 17. Mai 2022 16:09

Exception - Register + DataStack
 
Hallo ne Frage, es gibt ja Tools, die können bei einer Exception die CPU Register + DatenStack mit ausgeben.

Sowas wäre ja prinzipiell nicht schlecht, zB.: Könnte man da bei sowas
Delphi-Quellcode:
for i:=0 to Count-1 do Item[i].Free;
vermutlich dann anhander der Register automatisch sehen auf was der Zähler i gerade steht (zumindest wenn man sich dann den Assembler Code ansieht dann ja ganz sicher)

wie kommt man auf diese Register? bzw wie nennt sich das System mit dem man sowas auslesen kann?

Für mich ist es leider ja unlogisch, da ja die exception Routine das alles ja total verändert - daher verstehe ich das nicht wirklich ;)

Der schöne Günther 17. Mai 2022 16:47

AW: Exception - Register + DataStack
 
Verstanden habe ich das auch nie ganz, aber wenn du das schon im Delphi-Debugger nicht mehr sehen kannst, wie soll das dann noch ein externes Tool sehen können? Die Info scheint dann echt zu sein.

TurboMagic 17. Mai 2022 18:37

AW: Exception - Register + DataStack
 
Meinst du sowas wie MadExcept, Eurekalog oder das, was in der Jedi JCL enthalten ist?

Gruber_Hans_12345 18. Mai 2022 06:51

AW: Exception - Register + DataStack
 
ja genau madExcept zb kann eben die CPU Register anzeigen, und vorallem wenn mal ne exception in einer Schleife passiert wäre der CX oder was auch immer doch sehr interessant, oder eben generell der Daten-Stack.

Wenn man sich dann den Assemblercode ansieht dann kann man ja rausfinden wo die Schleifenvariable steht, und wüsste bei welchen Eintrag die Exception aufgetreten ist - wenn ich den Bug vom Kunden bekomme.

himitsu 18. Mai 2022 13:21

AW: Exception - Register + DataStack
 
Erstmal müsste diese Variable dann auch in den Registern liegen, was sie hier bestimmt nicht tut, da dieses Register über den Free/Destroy-Aufruf (und wer weiß was sonst noch alles darin passiert) ungültig/überschrieben würde.

Proderuren/Funktionen sind nicht verpflichtet Register sicherzustellen. (abgesehn von ein/zwei bestimmten Registern, wie EBX, in welchem diese Variable aber bestimmt nicht liegen wird)

In diesem Fall wird die Variable auf dem Stack liegen.




Wie: MSDN-Library durchsuchenGetThreadContext

Stevie 19. Mai 2022 00:15

AW: Exception - Register + DataStack
 
Zitat:

Zitat von himitsu (Beitrag 1506014)
Proderuren/Funktionen sind nicht verpflichtet Register sicherzustellen. (abgesehn von ein/zwei bestimmten Registern, wie EBX, in welchem diese Variable aber bestimmt nicht liegen wird)

Sehr komische und reichlich unfundierte Schlussfolgerung - gerade Zählvariablen sind prädestiniert dafür, in den nicht volatilen Registern zu liegen.

Gruber_Hans_12345 19. Mai 2022 07:39

AW: Exception - Register + DataStack
 
Das was da vermutlich einen strich durch die Rechnung machen wird, ist das eventuell dort wo die exception dann passiert, die CPU Register schon wieder für was anderes verwendet wurden.

Aber wenn man CPU + Stack von dem Zeitpunkt hat wann die Exception aufgetreten ist, dann könnte man es theoretisch ja schön rekonstruieren.

himitsu 19. Mai 2022 12:01

AW: Exception - Register + DataStack
 
Zitat:

Zitat von Stevie (Beitrag 1506057)
gerade Zählvariablen sind prädestiniert dafür, in den nicht volatilen Registern zu liegen.

Ja, das wären sie, wenn zwischendurch nicht anderer Code ausgeführt würde, welcher die Register potentiell überschreiben täte.

Eine kurze schleife, ohne Funktionsaufrufe (CALL), da darfst du das gerne machen, also wenn dein Codestrück die ganze Zeit über die volle Kontrolle über die Register besitzt.


Man kann sich bei sich selbst als Debugger registrieren.
Da kann dann bei einer Exception ein anderer Thread diese Register auslesen, ohne beim Lesen (CodeAusführen) "diese" Register zu beeinflussen, genauso wie es der Debugger von Delphi macht.

Stevie 23. Mai 2022 15:21

AW: Exception - Register + DataStack
 
Register auslesen ist relativ einfach (ich skizzier das mal für Windows).
Du ruftst MSDN-Library durchsuchenGetThreadContext auf und bekommst in der contextvariable die entsprechenden Registerwerte.

Allerdings, wie schon zuvor erwähnt, sind das dann die Werte zu diesem Zeitpunkt - also wenn das derselbe Thread ist wie der gerade diesen Code ausführende, liegt die Wahrscheinlichkeit hoch dass das nicht mehr der Wert ist, der im Code vor der Exception da drin stand - um das rekonstruieren müsste man rückwärts den Code disassembeln und das macht meines Wissens nach keins der Tools wie madExcept.

Beispiel: Ich hab den Code hier in nen ButtonClick geschrieben:

Delphi-Quellcode:
procedure ShowMsg(i: Integer);
begin
  ShowMessage(i.ToString);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 10 do
  begin
    RaiseLastOSError;
    ShowMsg(i);
  end;
end;
Der assembler code unter Win32 sieht so aus (mit
Delphi-Quellcode:
$O+W-
)

Code:
Unit1.pas.36: begin
0063A974 53               push ebx
Unit1.pas.37: for i := 1 to 10 do
0063A975 BB01000000       mov ebx,$00000001
Unit1.pas.39: RaiseLastOSError;
0063A97A E8F9CDE1FF      call RaiseLastOSError
Unit1.pas.40: ShowMsg(i);
0063A97F 8BC3             mov eax,ebx
0063A981 E89EFFFFFF      call ShowMsg
Unit1.pas.41: end;
0063A986 43               inc ebx
Unit1.pas.37: for i := 1 to 10 do
0063A987 83FB0B          cmp ebx,$0b
0063A98A 75EE            jnz $0063a97a
Unit1.pas.42: end;
0063A98C 5B              pop ebx
0063A98D C3               ret
Wenn der call auf RaiseLastOSError passiert ist ebx also 1, aber im angezeigten madExcept bugreport Fenster steht dort bei mir im "cpu regs" Tab 00000000 drin, da bis dahin ebx wiederverwendet wurde

himitsu 23. Mai 2022 18:00

AW: Exception - Register + DataStack
 
Das stimmt so weit auch, denn nicht "RaiseLastOSError" löst die Exception aus, sondern das passiert ja eh erst später, weiter drinnen.

Delphi-Quellcode:
procedure RaiseLastOSError;
begin
  RaiseLastOSError(GetLastError);
end;

procedure RaiseLastOSError(LastError: Integer);
var
  Error: EOSError;
begin
  if LastError <> 0 then
    Error := EOSError.CreateResFmt(@SOSError, [LastError,
      SysErrorMessage(LastError)])
  else
    Error := EOSError.CreateRes(@SUnkOSError);
  Error.ErrorCode := LastError;
  raise Error; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
end;
Mit DebugDCUs bis zum Raise, schauen was die CPU-Ansicht im Delphi sagt und das dann mit madExcept vergleichen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:51 Uhr.
Seite 1 von 2  1 2      

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