{
Summary:
Internal debug routines
## $Id: debug.pas,v 1.14 2004/04/10 22:24:03 druid Exp $
}
unit debug;
interface
uses
SysUtils;
procedure initDebug();
procedure cleanupDebug();
procedure reportException(E : Exception; const sourceFile : string = '');
implementation
uses
{$IFDEF WIN32}
Windows,
JclHookExcept,
JclDebug,
{$ENDIF}
{$IFDEF LINUX}
Libc,
{$ENDIF}
Classes,
console;
{$IFDEF WIN32}
procedure AnyExceptionNotify(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean);
var
list : TJclExceptFrameList;
begin
list := JclLastExceptFrameList;
// (definately a) handled exception, quit
if (list.items[0].FrameKind = efkAnyException) then
exit;
if (ExceptObj = nil) then
reportException(nil, 'debug.pas:AnyExceptionNotify')
else
reportException(ExceptObj as Exception, 'debug.pas:AnyExceptionNotify');
end;
function ExceptionFilter(ExceptionInfo: _EXCEPTION_POINTERS): longint; stdcall;
begin
//MessageBox(0, 'filter', 'filter', 0);
Result := 1;
end;
procedure reportException(E : Exception; const sourceFile : string = '');
var
a : integer;
strings : TStringList;
begin
if (E = nil) then
writeConsole('[EX ' + sourceFile + '] EUnknown', 1)
else
writeConsole('[EX ' + sourceFile + '] ' + E.ClassName + ': ' + E.Message, 1);
strings := TStringList.Create();
JclLastExceptStackListToStrings(strings, False, False, False);
if (strings.count > 0) then
begin
writeConsole('Stacktrace follows:', 1);
for a := 0 to strings.count - 1 do
writeConsole(strings[a], 1);
end
else
writeConsole('No stacktrace available.', 1);
strings.Free();
end;
{$ENDIF}
{$IFDEF LINUX}
function backtrace(var __array; __size : integer) : integer; cdecl; external 'libc.so.6' name 'backtrace';
procedure findSymbol(addr : pointer);
var
info : TDLInfo;
begin
dladdr(addr, info);
writeConsole('(' + IntToHex(integer(addr), 8) + ') ' + info.dli_sname + ' in ' + info.dli_fname, 1);
end;
procedure listBackTrace();
var
l, ret : integer;
x : array[0..15] of pointer;
begin
ret := backtrace(x, 16);
for l := 0 to ret - 1 do
findSymbol(x[l]);
end;
procedure reportException(E : Exception; const sourceFile : string = '');
begin
E := ExceptObject as Exception;
writeConsole('[EX ' + sourceFile + '] ' + E.ClassName + ': ' + E.Message, 1);
listBackTrace();
end;
{$ENDIF}
var
oldExceptProc : pointer;
procedure ExceptHandler(ExceptObject : TObject; ExceptAddr : Pointer);
begin
ExceptProc := oldExceptProc;
{$IFDEF LINUX}
reportException(ExceptObject as Exception, 'debug.pas:ExceptHandler');
{$ENDIF}
Halt(1);
end;
procedure initDebug();
begin
{$IFDEF WIN32}
// initialize the debug 'fail-safe device'
JclStackTrackingOptions := JclStackTrackingOptions + [stRawMode,stStaticModuleList,stExceptFrame];
SetUnhandledExceptionFilter(@ExceptionFilter);
JclStartExceptionTracking();
JclInitializeLibrariesHookExcept();
JclAddExceptNotifier(AnyExceptionNotify);
{$ENDIF}
oldExceptProc := exceptProc;
ExceptProc := @ExceptHandler;
end;
procedure cleanupDebug();
begin
{$IFDEF WIN32}
JclStopExceptionTracking();
{$ENDIF}
end;
end.