Recent

Author Topic: Workaround for SIGFPE bug in GDB for Windows?  (Read 6010 times)

EricGrange

  • New Member
  • *
  • Posts: 13
Workaround for SIGFPE bug in GDB for Windows?
« on: September 07, 2012, 09:08:57 am »
I'm encountering gdb crashes in Lazarus debugger whenever a floating point exception occurs, I first encountered it with TryStrToFloat

http://bugs.freepascal.org/view.php?id=22809

in that particular case that can be worked around by temporarily tweaking the 8087 CW and firing a FCLEX asm instruction.

However I've now found it also occurs on divide by zero, and probably a variety of other FPU situations (which are part of my unit tests), and it's rather crippling when debugging floating point maths code.

The GDB bug is described there

http://sourceware.org/bugzilla/show_bug.cgi?id=10004

It is 3 years old, last change was to unset target milestone, so the MS workaround in the KB they link doesn't seem likely to be implemented.

Any solution?

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: Workaround for SIGFPE bug in GDB for Windows?
« Reply #1 on: September 07, 2012, 05:57:14 pm »
1) You can debug your code on linux.
2) Here is a trick that works for me on win xp:
Code: [Select]
program project1;

{$mode delphi}

uses
   SysUtils,jwawinbase,JwaWinNT,math;

function MyExceptionHandler(ExceptionInfo: PEXCEPTION_POINTERS): Longint; stdcall;
var e:exception;
begin
  ExceptionInfo.ContextRecord.FloatSave.ControlWord:=ExceptionInfo.ContextRecord.FloatSave.ControlWord or $7F;
  ClearExceptions(false);
  result:=-1; //EXCEPTION_CONTINUE_EXECUTION;
  e:= exception.Create('my exception');
  raise e;
end;

var
   v : Double;
   h:pointer;
begin
  h:=AddVectoredExceptionHandler(1,@MyExceptionHandler);
  try
    v:=0;
    v:=1/v;
    TryStrToFloat('9e9999', v);
  except
    on e: Exception do begin
      writeln('Error:',e.ClassName);
      readln;
    end;
  end;
end.
The code installs a custom exception vector handler as the first handler. GDB breaks the code when a SIGFPE is received. Continue will hand the exception to MyExceptionHandler. It modifies the FPU ControlWord in the Context (indirectly because the code will continue after loading registers from the Context), clear the FPU exception (similar to FCLEX), create a new exception and raise that one. The new exception will trigger your pascal exception handling.

The code will handle all exceptions the same way. You can use ExceptionInfo.ExceptionRecord.ExceptionCode to find out what the exception is about. You can also restore the FPU mask in your pascal exception handling. Hopefully that is enough to debug your fp code.

 

TinyPortal © 2005-2018