![]() |
StackTrace-Ausgabe unter MacOS
Hi,
wie gebt ihr den vollständigen StackTrace unter MacOS aus? Für Windows nutze ich MadExcept, für iOS und Android hatte ich schon mal brauchbaren Code gefunden. Nur für MacOS (und Linux) fehlt mir noch ein brauchbares Pendant. Grüße, Philipp |
AW: StackTrace-Ausgabe unter MacOS
|
AW: StackTrace-Ausgabe unter MacOS
Der dort dokumentierte Code ist leider nicht vollständig. Man muss sich die Unit SBMapFiles noch selber zusammenbauen. Und mir scheint, dass die Stacktrace-Ausgabe ohne dieseMapping relativ nutzlos ist. Copy&Paste reicht also nicht aus um dies zu testen.
|
AW: StackTrace-Ausgabe unter MacOS
Hallo,
ja, gerade noch mal genauer gelesen. Es sind ja 2 Ansätze: 1. unit MyExceptionHandler; 2. mit Hilfe der undokumentierten SBxx-Unit. |
AW: StackTrace-Ausgabe unter MacOS
So, ich habe mir jetzt den Map-File-Mapper selbst gebaut und damit bekommt man halbwegs aussagekräftige StackTraces ausgegeben.
Aber irgendwie traurig, dass man dafür selbst eine solche Funktion implementieren muss. Sind nur 220 Zeilen, aber trotzdem würde ich mir so etwas von Emba frei Haus wünschen. |
AW: StackTrace-Ausgabe unter MacOS
|
AW: StackTrace-Ausgabe unter MacOS
Ich bin auch EWIG auf der Suche nach einem OSX exception handler. Kannst Du Deinen Code nicht mit uns teilen, damit das Rad nicht nochmal erfunden werden muss?
|
AW: StackTrace-Ausgabe unter MacOS
Hier ist mein Code, ein paar kleinere Anpassungen sind sicherlich notwendig. MyLog ist bei mir ein Wrapper zu TMSLogging.
FileUtils liest einfach nur eine TStringList ein, das sollte einfach zu ersetzen sein. Voraussetzung ist aber, dass du das Map-File erzeugst und mit deployst.
Delphi-Quellcode:
unit MyMacOSExceptionHandler;
interface var mapFilename:String; function getFunctionNameExt(hexException:String):String; implementation uses Posix.Base, SysUtils, MyLog, System.Generics.Collections, FileUtils, System.Classes, IntegerStringList; function backtrace(result: PNativeUInt; size: Integer): Integer; cdecl; external libc name '_backtrace'; function _NSGetExecutablePath(buf: PAnsiChar; BufSize: PCardinal): Integer; cdecl; external libc name '__NSGetExecutablePath'; var PrevRaiseException: function(Exc: Pointer): LongBool; cdecl; mapDict: TIntegerStringList; const MaxDepth = 20; SkipFrames = 3; procedure LoadMapFile(); var //FileName: array[0..255] of AnsiChar; //Len: Integer; mapFile:TStringList; i,firstEntry:integer; start1,start2,start3,start4:Int64; key:Int64; add,value:String; begin if (MapDict = nil) then begin mapDict:=TIntegerStringList.create(); //Len := Length(FileName); //_NSGetExecutablePath(@FileName[0], @Len); //if FileExists(ChangeFileExt(FileName, '.map')) then start1:=0; start2:=0; start3:=0; start4:=0; //start5:=0; if (FileExists(mapFilename)) then begin //mapFile:=TFileUtils.readFile(ChangeFileExt(FileName, '.map')); mapFile:=TFileUtils.readFile(mapFileName); firstEntry:=-1; for i:=0 to mapFile.count-1 do begin if (pos('Start',mapFile[i])>0) then begin start1:=StrToInt('$'+copy(mapFile[i+1],7,8)); start2:=StrToInt('$'+copy(mapFile[i+2],7,8)); start3:=StrToInt('$'+copy(mapFile[i+3],7,8)); start4:=StrToInt('$'+copy(mapFile[i+4],7,8)); //start5:=StrToInt('$'+copy(mapFile[i+5],7,8)); break; end; end; for i:=0 to mapFile.count-1 do begin if (pos('Address',mapFile[i])>0) and (pos('Publics by Name',mapFile[i])>0) then begin firstEntry:=i+2; break; end; end; if (firstEntry>-1) then begin for i:=firstEntry to mapFile.count-1 do begin if (mapFile[i]='') then break; add:=copy(mapFile[i],2,4); key:=StrToInt64('$'+copy(mapFile[i],7,8)); value:=copy(mapFile[i],22); if (add='0001') then key:=start1+key else if (add='0002') then key:=start2+key else if (add='0003') then key:=start3+key else if (add='0004') then key:=start4+key; //else if (add='0005') then // key:=IntToHex(start5+StrToInt64('$'+key),8); mapDict.add(TIntegerStringEntry.create(key,value)); end; mapDict.sort(mapDict.comparer); end; end else log.info('Can''t find Map-File: '+mapFilename); end; end; function getFunctionName(exceptionInt:Int64):String; var i:integer; begin Result:='???'; for i:=1 to mapDict.count-1 do begin if (mapDict[i].key>exceptionInt) then begin Result:=mapDict[i-1].value; break; end; end; end; function getFunctionNameExt(hexException:String):String; begin Result:=getFunctionName(StrToInt64('$'+hexException)); end; procedure ShowCurrentStack; var StackLog: PNativeUInt; //array[0..10] of Pointer; Cnt: Integer; I: Integer; begin {$POINTERMATH ON} if (mapDict=nil) then loadMapFile(); GetMem(StackLog, SizeOf(Pointer) * MaxDepth); try Cnt := backtrace(StackLog, MaxDepth); for I := SkipFrames to Cnt - 1 do begin if StackLog[I] = $BE00EF00 then begin WriteLn('---'); Break; end; log.error(IntToHex(StackLog[I],8)+' '+getFunctionName(StackLog[I])); end; finally FreeMem(StackLog); end; {$POINTERMATH OFF} end; procedure InstallExceptionHandler; forward; procedure UnInstallExceptionHandler; forward; var InRaiseException: Boolean; function RaiseException(Exc: Pointer): LongBool; cdecl; begin InRaiseException := True; ShowCurrentStack; Result := PrevRaiseException(Exc); InRaiseException := False; end; procedure InstallExceptionHandler; var U: TUnwinder; begin GetUnwinder(U); Assert(Assigned(U.RaiseException)); PrevRaiseException := U.RaiseException; U.RaiseException := RaiseException; SetUnwinder(U); mapDict:=nil; end; procedure UnInstallExceptionHandler; var U: TUnwinder; begin GetUnwinder(U); U.RaiseException := PrevRaiseException; SetUnwinder(U); end; initialization InstallExceptionHandler; end.
Delphi-Quellcode:
unit IntegerStringList;
interface uses Generics.Collections,System.SysUtils,System.Classes, System.Generics.Defaults, System.Math; type TIntegerStringEntry = class(TObject) public key:Int64; value:String; constructor create(key:Int64;value:String); end; TIntegerStringList = class(TObjectList<TIntegerStringEntry>) public Comparer: IComparer<TIntegerStringEntry>; constructor create(); overload; end; implementation constructor TIntegerStringEntry.create(key:Int64;value:String); begin self.key:=key; self.value:=value; end; constructor TIntegerStringList.create(); begin Comparer := TDelegatedComparer<TIntegerStringEntry>.Create( function(const Left, Right: TIntegerStringEntry): Integer begin if (left.key<right.key) then Result:=-1 else if (left.key>right.key) then Result:=1 else Result := 0; end); inherited create(true); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz